The collation determines the comparison semantics.
If I try
CREATE TABLE [word](
[id] [int] IDENTITY(0,1) NOT NULL,
[value] [nvarchar](255) COLLATE Latin1_General_100_CI_AS NULL
);
It only returns ἀπὸ
.
Changing the suffix to AI
for accent insensitive returns ἀπό
also.
On my install I have tried every collation and 1526
return 1
(presumably AS
and BIN
collations), 1264
return 2 rows (presumably AI
) and 1095
return 8
.
From a quick look through this last group looks to include all the SQL
collations and 90
collations whereas all the 100
ones are in the first 2 groups so I presume this is some issue that has been fixed in the 2008 batch of collations. (See What's New in SQL Server 2008 Collations)
Script to try this yourself
DECLARE @Results TABLE
(
Count INT,
Collation SYSNAME
)
SET NOCOUNT ON;
DECLARE @N SYSNAME;
DECLARE @C1 AS CURSOR;
SET @C1 = CURSOR FAST_FORWARD FOR
SELECT name
FROM sys.fn_helpcollations();
OPEN @C1;
FETCH NEXT FROM @C1 INTO @N ;
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT @Results
EXEC('SELECT COUNT(*), ''' + @N + ''' from word where value = N''ἀπὸ'' COLLATE ' + @N)
FETCH NEXT FROM @C1 INTO @N ;
END
SELECT *
FROM @Results
ORDER BY Count DESC
This is a gaps-and-islands problem. Assuming there are no gaps or duplicates in the same id_set
set:
WITH partitioned AS (
SELECT
*,
number - ROW_NUMBER() OVER (PARTITION BY id_set) AS grp
FROM atable
WHERE status = 'FREE'
),
counted AS (
SELECT
*,
COUNT(*) OVER (PARTITION BY id_set, grp) AS cnt
FROM partitioned
)
SELECT
id_set,
number
FROM counted
WHERE cnt >= 3
;
Here's a SQL Fiddle demo* link for this query: http://sqlfiddle.com/#!1/a2633/1.
UPDATE
To return only one set, you could add in one more round of ranking:
WITH partitioned AS (
SELECT
*,
number - ROW_NUMBER() OVER (PARTITION BY id_set) AS grp
FROM atable
WHERE status = 'FREE'
),
counted AS (
SELECT
*,
COUNT(*) OVER (PARTITION BY id_set, grp) AS cnt
FROM partitioned
),
ranked AS (
SELECT
*,
RANK() OVER (ORDER BY id_set, grp) AS rnk
FROM counted
WHERE cnt >= 3
)
SELECT
id_set,
number
FROM ranked
WHERE rnk = 1
;
Here's a demo for this one too: http://sqlfiddle.com/#!1/a2633/2.
If you ever need to make it one set per id_set
, change the RANK()
call like this:
RANK() OVER (PARTITION BY id_set ORDER BY grp) AS rnk
Additionally, you could make the query return the smallest matching set (i.e. first try to return the first set of exactly three consecutive numbers if it exists, otherwise four, five etc.), like this:
RANK() OVER (ORDER BY cnt, id_set, grp) AS rnk
or like this (one per id_set
):
RANK() OVER (PARTITION BY id_set ORDER BY cnt, grp) AS rnk
* The SQL Fiddle demos linked in this answer use the 9.1.8 instance as the 9.2.1 one doesn't appear to be working at the moment.
Best Answer
You could do something like this: