I want to find out the longest sequence of letter in a string
e.g. in the word Honorificabcdwert , the output will be abcd.
How can I do it?
My idea is to get the Ascii and then count the sequence until it breaks at some point. But I was able to proceed with only
DECLARE #t TABLE(ID INT IDENTITY,String VARCHAR(100))
INSERT INTO #t SELECT 'Honorificabcdwert'
;with Get_Individual_Chars_Cte AS
(
SELECT
ID
,Row_ID =ROW_NUMBER() Over(PARTITION by ID Order by ID)
,SUBSTRING(String,Number,1) AS [Char]
,ASCII(SUBSTRING(String,Number,1)) AS [Ascii Value]
FROM #t
INNER JOIN master.dbo.spt_values ON
Number BETWEEN 1 AND LEN(String)
AND type='P'
)
Select * from Get_Individual_Chars_Cte
After this I don't know what to do. Help needed for this or any other way of doing so.
Will this help
DECLARE #t TABLE(ID INT IDENTITY,String VARCHAR(100))
INSERT INTO #t
SELECT 'Honorificabcdwert' UNION ALL
SELECT 'AbCdEfxy' UNION ALL
SELECT 'abc1234defg' UNION ALL
SELECT 'XYZABCPPCKLMIDBABC' UNION ALL
SELECT 'MNOP$%^&~()MNOPQRS;:'
SELECT ID, OriginalString,Sequence
FROM (SELECT ID, REPLACE(string,'%','') AS Sequence,OriginalString,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY LEN(string) DESC, string) AS rn
FROM (SELECT OriginalString = b.String, CASE WHEN b.String LIKE a.strings THEN a.strings ELSE NULL END AS string,
b.ID, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY LEN(strings) DESC, strings) AS rn
FROM (SELECT COALESCE('%' + b.strings+a.strings + '%','%' + a.strings + '%') AS strings
FROM (SELECT SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ',t1.N,t2.N-t1.N+1) AS strings, t1.N
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),
(9),(10),(11),(12),(13),(14),(15),
(16),(17),(18),(19),(20),(21),(22),
(23),(24),(25),(26)) t1(N)
CROSS JOIN (VALUES(1),(2),(3),(4),(5),(6),(7),(8),
(9),(10),(11),(12),(13),(14),(15),
(16),(17),(18),(19),(20),(21),(22),
(23),(24),(25),(26)) t2(N)
WHERE t1.N <= t2.N) a
LEFT OUTER JOIN (SELECT REVERSE(SUBSTRING('ZYXWVUTSRQPONMLKJIHGFEDCBA',1,N)) AS strings, 1 AS ID
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),
(9),(10),(11),(12),(13),(14),(15),
(16),(17),(18),(19),(20),(21),(22),
(23),(24),(25),(26)) t1(N)
UNION ALL SELECT '', 1) b ON a.N = b.ID) a
CROSS JOIN #t b) a ) a
WHERE a.rn = 1
ORDER BY a.ID
Result
ID OriginalString Sequence
1 Honorificabcdwert ABCD
2 AbCdEfxy ABCDEF
3 abc1234defg DEFG
4 XYZABCPPCKLMIDBABC XYZABC
5 MNOP$%^&~()MNOPQRS;: MNOPQRS
Based on your inputs provided in the course of discussion with #Martin Smith, the program is being developed. Please test it and let me know if it satisfies your requirement.
For consecutive rows with characters rising in alphabetical order (equating alphabetical order with ASCII order here) ROW_NUMBER() OVER (ORDER BY Row_ID) - [Ascii Value] will be the same.
This is not sufficient on its own however as for the string ABCZE that would put E in the same group as ABC so then you need a second operation to find gaps in that grouping sequence.
Something like the following should do it.
DECLARE #t TABLE(ID INT IDENTITY,String VARCHAR(100))
INSERT INTO #t SELECT 'Honorificabcdwfrt'
;with Get_Individual_Chars_Cte AS
(
SELECT
ID
,Row_ID =ROW_NUMBER() Over(PARTITION by ID Order by ID)
,SUBSTRING(String,number,1) AS [Char]
,ASCII(SUBSTRING(String,number,1)) AS [Ascii Value]
FROM #t
INNER JOIN master.dbo.spt_values ON
number BETWEEN 1 AND LEN(String)
AND type='P'
)
, T1 AS
(
Select *,
ROW_NUMBER() OVER (ORDER BY Row_ID) - [Ascii Value] AS RN
from Get_Individual_Chars_Cte
), T2 AS
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY Row_ID) -
ROW_NUMBER() OVER (PARTITION BY RN ORDER BY Row_ID) AS Grp
FROM T1
)
SELECT TOP 1 WITH TIES *
FROM T2
ORDER BY COUNT(*) OVER (PARTITION BY RN, Grp) DESC
Related
For example:
pk_ref fk
====== ===
1 a
1 b
1 c
2 a
2 b
2 d
How do I do a query like the "pseudo" query:
select distinc pk_ref
where fk in all('a', 'c');
The return query result must match all given values for the foreign key in the list.
The result should be:
1
While the following select must not return any records.
select distinc pk_ref
where fk in all('a', 'c', 'd');
How do I do that?
Try this
select pk_ref
from yourtable
group by pk_ref
having count(case when fk = 'a', then 1 end) >= 1
and count(case when fk = 'c' then 1 end) >= 1
To do it dynamically. (considering you are using SQL SERVER)
Create a split string function and pass the input as comma separated values
Declare #input varchar(8000)= 'a,c',#cnt int
set #cnt = len(#input)-len(replace(#input,',','')) + 1
select pk_ref
from yourtable
Where fk in (select split_values from udf_splitstring(#input , ','))
group by pk_ref
having count(Distinct fk) >= #cnt
You can create a split string function from the below link
https://sqlperformance.com/2012/07/t-sql-queries/split-strings
:list is the input list (bind variable). The difference of length() return values is the number of commas in the bind variable. This query, or something very close to it, should work in pretty much any DB product. Tested in Oracle.
select pk_ref
from tbl -- enter your table name here
where ',' || :list || ',' like '%,' || fk || ',%'
group by pk_ref
having count(distinct fk) = 1 + length(:list) - length(replace(:list, ',', ''))
If you can pass the IN operator values as Set, then you can do this as below
Schema:
SELECT * INTO #TAB FROM (
SELECT 1 ID, 'a' FK
UNION ALL
SELECT 1, 'b'
UNION ALL
SELECT 1, 'c'
UNION ALL
SELECT 2, 'a'
UNION ALL
SELECT 2, 'b'
UNION ALL
SELECT 2, 'd'
UNION ALL
SELECT 1, 'a'
)AS A
Used CTE to make 'a','c' as Set
;WITH CTE AS (
SELECT 'a' FK --Here 'a','c' passed as a Set through CTE
UNION
SELECT 'c'
)
,FINAL AS(
SELECT DENSE_RANK() OVER (PARTITION BY ID ORDER BY (FK))AS COUNT_ID, ID, FK
FROM #TAB where FK IN (select FK FROM CTE)
)
SELECT ID FROM FINAL WHERE COUNT_ID>=(SELECT COUNT( FK) FROM CTE)
Select pk_ref where fk='a' and pk_ref in (select pk_ref where fk='c' from yourtable) from yourtable;
or
select pk_ref where fk='a' from yourtable intersect select pk_ref where fk='c' from yourtable;
DECLARE #inputVariable VARCHAR(200) = 'a,b,c,d'
DECLARE #inputValue INT
DECLARE #tblInput TABLE
(
FK VARCHAR(100)
)
INSERT INTO #tblInput
SELECT SUBSTRING( #inputVariable+',',RN,1)
FROM (SELECT TOP 100 ROW_NUMBER() OVER(ORDER BY s.object_id) RN
FROM sys.objects s) s
where LEN(#inputVariable) >= RN
AND SUBSTRING(','+ #inputVariable,RN,1) = ','
SELECT #inputValue = COUNT(1) FROm #tblInput
--#inputVariable
DECLARE #tbl TABLE
(
ID INT,
FK VARCHAR(100)
)
INSERT INTO #tbl
SELECT 1 ID, 'a' FK
UNION ALL
SELECT 1, 'b'
UNION ALL
SELECT 1, 'c'
UNION ALL
SELECT 2, 'a'
UNION ALL
SELECT 2, 'b'
UNION ALL
SELECT 2, 'd'
UNION ALL
SELECT 1, 'a'
SELECT t.ID ,COUNT(DISTINCT t.FK)
FROM #tbl t
INNER JOIn #tblInput ti
ON t.FK = ti.FK
GROUP BY ID
HAVING COUNT(DISTINCT t.FK) = #inputValue
I have the table with data:
And for this table I need to create pegination by productId column. I know about LIMIT N,M, but it works with rows and not with groups. For examle for my table with pegination = 2 I expect to retrieve all 9 records with productId = 1 and 2 (the number of groups is 2).
So how to create pegination by numbers of groups ?
I will be very thankfull for answers with example.
One way to do pagination by groups is to assign a product sequence to the query. Using variables, this requires a subquery:
select t.*
from (select t.*,
(#rn := if(#p = productid, #rn + 1,
if(#rn := productid, 1, 1)
)
) as rn
from table t cross join
(select #rn := 0, #p := -1) vars
order by t.productid
) t
where rn between X and Y;
With an index on t(productid), you can also do this with a subquery. The condition can then go in a having clause:
select t.*,
(select count(distinct productid)
from t t2
where t2.productid <= t.productid)
) as pno
from t
having pno between X and Y;
Try this:
select * from
(select * from <your table> where <your condition> group by <with your group>)
LIMIT number;
**castID**
nm0000116
nm0000116
nm0000116
nm0000116
nm0000116
nm0634240
nm0634240
nm0798899
This is my table (created as a view). Now I want to list the castID which has the most count (in this case which is nm0000116, and how many occurences/count it has in this table ( should be 5 times) and I'm not quite sure which query to use
try
Select CastId, count(*) countOfCastId
From table
Group By CastId
Having count(*)
= (Select Max(cnt)
From (Select count(*) cnt
From table
Group By CastId) z)
SELECT
MAX(E),
castId
FROM
(SELECT COUNT(castId) AS E,castId FROM [directors winning movies list] GROUP BY castId) AS t
You could just return the topmost count using LIMIT:
SELECT castID,
COUNT(*) AS Cnt
FROM atable
GROUP BY castID
ORDER BY Cnt DESC
LIMIT 1
;
However, if there can be ties, the above query would return only one row. If you want all the "winners", you could take the count from the above query as a scalar result and compare it against all the counts to return only those that match:
SELECT castID,
COUNT(*) AS Cnt
FROM atable
GROUP BY castID
HAVING COUNT(*) = (
SELECT COUNT(*)
FROM atable
GROUP BY castID
ORDER BY Cnt DESC
LIMIT 1
)
;
(Basically, same as Charles Bretana's approach, it just derives the top count differently.)
Alternatively, you could use a variable to rank all the counts and then return only those that have the ranking of 1:
SELECT castID,
Cnt
FROM (
SELECT castID,
COUNT(*) AS Cnt,
#r := IFNULL(#r, 0) + 1 AS r
FROM atable
GROUP BY castID
ORDER BY Cnt DESC
) AS s
WHERE r = 1
;
Please note that with the above method the variable must either not exist or be pre-initialised with a 0 or NULL prior to running the query. To be on the safe side, you could initialise the variable directly in your query:
SELECT s.castID,
s.Cnt
FROM (SELECT #r := 0) AS x
CROSS JOIN
(
SELECT castID,
COUNT(*) AS Cnt,
#r := #r + 1 AS r
FROM atable
GROUP BY castID
ORDER BY Cnt DESC
) AS s
WHERE s.r = 1
;
Let's say I have the following very simple schema:
Create Table MyTable (
PrimaryKey int,
Column1 datetime.
Column2 int
)
I need a query that orders the data based on Column1, and finds the first 10 consecutive rows where the value of Column2 in the current row is greater than the value of column2 in the prior row.
Q is used to get a ranking value rn ordered by Column1. Added in PrimaryKey in case there are ties in Column1. C is a recursive CTE that loops from the top ordered by rn incrementing cc for each increasing value of Column2. It will break from the recursion when cc reaches 10. Finally get the last 10 rows from C. The where clause takes care of the case when there are no 10 consecutive increasing values.
with Q as
(
select PrimaryKey,
Column1,
Column2,
row_number() over(order by Column1, PrimaryKey) as rn
from MyTable
),
C as
(
select PrimaryKey,
Column1,
Column2,
rn,
1 as cc
from Q
where rn = 1
union all
select Q.PrimaryKey,
Q.Column1,
Q.Column2,
Q.rn,
case
when Q.Column2 > C.Column2 then C.cc + 1
else 1
end
from Q
inner join C
on Q.rn - 1 = C.rn
where C.cc < 10
)
select top 10 *
from C
where 10 in (select cc from C)
order by rn desc
option (maxrecursion 0)
Version 2
As Martin Smith pointed out in a comment, the above query has really bad performance. The culprit is the first CTE. The version below use table variable to hold the ranked rows. The primary key directive on rn creates an index that will be used in the join in the recursive part of the query. Apart from the table variable this does the same as above.
declare #T table
(
PrimaryKey int,
Column1 datetime,
Column2 int,
rn int primary key
);
insert into #T
select PrimaryKey,
Column1,
Column2,
row_number() over(order by Column1, PrimaryKey) as rn
from MyTable;
with C as
(
select PrimaryKey,
Column1,
Column2,
rn,
1 as cc
from #T
where rn = 1
union all
select T.PrimaryKey,
T.Column1,
T.Column2,
T.rn,
case
when T.Column2 > C.Column2 then C.cc + 1
else 1
end
from #T as T
inner join C
on T.rn = C.rn + 1
where C.cc < 10
)
select top 10 *
from C
where 10 in (select cc from C)
order by rn desc
option (maxrecursion 0)
i have a table MEN in sql server 2008 that contain 150 rows.
how i can show only the even or only the odd rows ?
Check out ROW_NUMBER()
SELECT t.First, t.Last
FROM (
SELECT *, Row_Number() OVER(ORDER BY First, Last) AS RowNumber
--Row_Number() starts with 1
FROM Table1
) t
WHERE t.RowNumber % 2 = 0 --Even
--WHERE t.RowNumber % 2 = 1 --Odd
Assuming your table has auto-numbered field "RowID" and you want to select only records where RowID is even or odd.
To show odd:
Select * from MEN where (RowID % 2) = 1
To show even:
Select * from MEN where (RowID % 2) = 0
FASTER: Bitwise instead of modulus.
select * from MEN where (id&1)=0;
Random question: Do you actually use uppercase table names?
Usually uppercase is reserved for keywords. (By convention)
odd number query:
SELECT *
FROM ( SELECT rownum rn, empno, ename
FROM emp
) temp
WHERE MOD(temp.rn,2) = 1
even number query:
SELECT *
FROM ( SELECT rownum rn, empno, ename
FROM emp
) temp
WHERE MOD(temp.rn,3) = 0
For even values record :
select * from www where mod(salary,2)=0;
For odd values record:
select * from www where mod(salary,2)!=0;
Try this :
odd :
select * from(
SELECT col1, col2, ROW_NUMBER() OVER(ORDER BY col1 DESC) AS 'RowNumber',
FROM table1
) d where (RowNumber % 2) = 1
even :
select * from(
SELECT col1, col2, ROW_NUMBER() OVER(ORDER BY col1 DESC) AS 'RowNumber',
FROM table1
) d where (RowNumber % 2) = 0
SELECT * FROM (SELECT ROW_NUMBER () OVER (ORDER BY sal DESC) row_number, sr,sal FROM empsal) a WHERE (row_number%2) = 1
and
SELECT * FROM (SELECT ROW_NUMBER () OVER (ORDER BY sal DESC) row_number, sr,sal FROM empsal) a WHERE (row_number%2) = 0
SELECT *
FROM
(
SELECT rownum rn, empno, ename
FROM emp
) temp
WHERE MOD(temp.rn,2) = 1
select * from Tablename
where id%2=0
Following is for fetching even number::
Select * from MEN where Men_ID%2=0;
Following is for fetching odd number::
Select * from MEN where Men_ID%2!=0;
Here MEN is your table_name Men_ID is the column in MEN Table.
Try following
SELECT * FROM Worker WHERE MOD (WORKER_ID, 2) <> 0;
Here’s a simple and straightforward answer to your question, (I think).
I am using the TSQL2012 sample database and I am returning only even or odd rows based on “employeeID” in the “HR.Employees” table.
USE TSQL2012;
GO
Return only Even numbers of the employeeID:
SELECT *
FROM HR.Employees
WHERE (empid % 2) = 0;
GO
Return only Odd numbers of the employeeID:
SELECT *
FROM HR.Employees
WHERE (empid % 2) = 1;
GO
Hopefully, that’s the answer you were looking for.
To fetch even records
select *
from (select id,row_number() over (order by id) as r from table_name) T
where mod(r,2)=0;
To fetch odd records
select *
from (select id,row_number() over (order by id) as r from table_name) T
where mod(r,2)=1;
Oracle Database
ODD ROWS
select * from (select mod(rownum,2) as num , employees.* from employees) where num =0;
EVEN ROWS
select * from (select mod(rownum,2) as num , employees.* from employees) where num =1;
To select an odd id from a table:
select * from Table_Name where id%2=1;
To select an even id from a table:
select * from Table_Name where id%2=0;
We can achieve by this
Query To Find ODD Records
/*Query To Find ODD Result using CTE */
WITH EVEN_ODD_RESULT AS
(
select *, ROW_NUMBER() OVER (ORDER BY CountryID) AS ROWNUM
FROM schema.Country_TBL
)
SELECT * FROM EVEN_ODD_RESULT
WHERE (EVEN_ODD_RESULT.ROWNUM % 2) =1
Query To Find EVEN Records
/*Query To Find EVEN Result using CTE */
WITH EVEN_ODD_RESULT AS
(
select *, ROW_NUMBER() OVER (ORDER BY CountryID) AS ROWNUM
FROM schema.Country_TBL
)
SELECT * FROM EVEN_ODD_RESULT
WHERE (EVEN_ODD_RESULT.ROWNUM % 2) = 0
Thank You
for SQL > odd:
select * from id in(select id from employee where id%2=1)
for SQL > Even:
select * from id in(select id from employee where id%2=0).....f5