How to generate proper SQL request - sql

I have a database where ID is int value 7 or 8 digits (2500859 or 15201234) long so i need to generate correct SQL request.
I tried to
SELECT MAX(Id) FROM Table WHERE FORMAT(Id, '0#######') LIKE '25'
but it doesn't works.
Could you please me generate correct request.
SELECT MAX(Id) FROM Table WHERE FORMAT(Id, '0#######') LIKE '25'
result is 0

I've solved it by using the following query:
SELECT MAX(CAST(RIGHT(FORMAT(Id, '0#######'),5) as INT))
FROM Column
WHERE CAST(LEFT(FORMAT(Id, '0#######'),3) AS INT) = Number"
This string returns the output which I asked for.

Postgresql:
select max(id) from kkkk where length(id::varchar) =7;
select max(id) from kkkk where length(id::varchar) =8;
------------ method 1
select * from kkkk where length(id::varchar) =7;
select * from kkkk where length(id::varchar) =8;
---------------method 2
select
case when length(id::varchar) =7 then id end as "ids with 7 caracters",
case when length(id::varchar) =8 then id end as "ids with 8 caracters"
from kkkk
Demo

Related

PLSQL: How do I count the occurrences of a substring in all values in a column

I have a table like this in an Oracle database:
substring
string
abc
123-def-abc
def
123-def
ghi
123-def-ghi
jkl
123-456-jkl
mno
123-456-jkl-mno
I need to count the occurrences of each substring in all the rows of the string column. An example result would be:
substring
string
count
abc
123-def-abc
1
def
123-def
3
ghi
123-def-ghi
1
jkl
123-456-jkl
2
mno
123-456-jkl-mno
1
How can I achieve this result?
Few solutions:
DBFiddle
cross apply (or lateral or cross join):
select *
from t
cross apply(
select count(*) cnt
from t t2
where t2.string like '%'||t.substring||'%'
) a
order by substring;
subquery:
select
t.*
,(
select count(*) cnt
from t t2
where t2.string like '%'||t.substring||'%'
) cnt
from t
order by substring;
connect by:
select
substring,string,count(*)
from (
select
connect_by_root substring as substring
,connect_by_root string as string
from t
connect by nocycle
level<=2
and string like '%'||(prior t.substring)||'%'
)
group by substring,string
order by substring;
model:
select
substring,string,cnt
from t
model
dimension by (substring,string)
measures(0 as cnt,string as string2)
rules(
cnt[any,any] order by substring = count(*)[any,string like '%'||cv()||'%']
)
order by substring;
xmlquery + xmlagg:
select--+ NO_XML_QUERY_REWRITE
substring,string,
xmlcast(
xmlquery(
'count($D/ROW/VAL[contains(., $X)])'
passing
xmlelement("ROW", (xmlagg(xmlelement(VAL, string)) over())) as d,
substring as x
returning content) as number) as cnt
from t
order by substring;
This might be one option.
For sample data
SQL> with test (substring, string) as
2 (select 'abc', '123-def-abc' from dual union all
3 select 'def', '123-def' from dual union all
4 select 'ghi', '123-def-ghi' from dual union all
5 select 'jkl', '123-456-jkl' from dual union all
6 select 'mno', '123-456-jkl-mno' from dual
7 ),
check whether substring exists in string (and use cross join, as you have to check all combinations)
8 temp as
9 (select a.substring,
10 case when instr(b.string, a.substring) > 1 then 1 else 0 end cnt
11 from test a cross join test b
12 -- group by a.substring
13 )
Finally, return the result by joining the "original" table and the temp CTE:
14 select a.substring, a.string, sum(b.cnt) cnt
15 from test a join temp b on a.substring = b.substring
16 group by a.substring, a.string
17 order by a.substring;
SUB STRING CNT
--- --------------- ----------
abc 123-def-abc 1
def 123-def 3
ghi 123-def-ghi 1
jkl 123-456-jkl 2
mno 123-456-jkl-mno 1
SQL>
This can be done with a CTE with 2 calls to the original tables, one using distinct to get the substrings and another to get all the occurrences of each string, cross-joined. We then use aggregation to count the number of occurrences of each match.
create table if not exists strings(
substrin varchar(3),
strin varchar(20)
);
delete from strings;
insert into strings values('abc','123-def-abc');
insert into strings values('def','123-def');
insert into strings values('def','123-def');
insert into strings values('ghi','123-def-ghi');
insert into strings values('jkl','123-456-jkl');
insert into strings values('jkl','123-456-jkl');
insert into strings values('mno','123-456-jkl-mno');
with sss as
( select s1.substrin sb, s2.strin sg
from (Select distinct substrin from strings ) s1,
strings s2)
select
sb 'substring',
sg 'string',
count(*) 'count'
from sss
where sg like concat('%',sb,'%')
group by sg,sb;
Note that this does not give the total number of lines which match the substring but the number of occurrences of each pair.

How to union a hardcoded row after each grouped result

After every group / row i want to insert a hardcoded dummy row with a bunch of 'xxxx' to act a separator.
I would like to use oracle sql to do this query. i can execute it using a loop but i don't want to use plsql.
As the others suggest, it is best to do it on the front end.
However, if you have a burning need to be done as a query, here is how.
Here I did not use the rownum function as you have already done. I assume, your data is returned by a query, and you can replace my table with your query.
I made few more assumptions, as you have data with row numbers in it.
[I am not sure what do you mean by not PL/SQL]
Select Case When MOD(rownm, 2) = 0 then ' '
Else to_char((rownm + 1) / 2) End as rownm,
name, total, column1
From
(
select (rownm * 2 - 1) rownm,name, to_char(total) total ,column1 from t
union
SELECT (rownm * 2) rownm,'XXX' name, 'XXX' total, 'The row act .... ' column1 FROM t
) Q
Order by Q.rownm;
and here is the fiddle
Since you're already grouping the data, it might be easier to use GROUPING SETS instead of a UNION.
Grouping sets let you group by multiple sets of columns, including the same set twice to duplicate rows. Then the GROUP_ID function can be used to determine when the fake values should be used. This code will be a bit smaller than a UNION approach, and should be faster since it doesn't need to reference the table multiple times.
select
case when group_id() = 0 then name else '' end name,
case when group_id() = 0 then sum(some_value) else null end total,
case when group_id() = 1 then 'this rows...' else '' end column1
from
(
select 'jack' name, 22 some_value from dual union all
select 'jack' name, 1 some_value from dual union all
select 'john' name, 44 some_value from dual union all
select 'john' name, 1 some_value from dual union all
select 'harry' name, 1 some_value from dual union all
select 'harry' name, 1 some_value from dual
) raw_data
group by grouping sets (name, name)
order by raw_data.name, group_id();
You can use row generator technique (using CONNECT BY) and then use CASE..WHEN as follows:
SQL> SELECT CASE WHEN L.LVL = 1 THEN T.ROWNM END AS ROWNM,
2 CASE WHEN L.LVL = 1 THEN T.NAME
3 ELSE 'XXX' END AS NAME,
4 CASE WHEN L.LVL = 1 THEN TO_CHAR(T.TOTAL)
5 ELSE 'XXX' END AS TOTAL,
6 CASE WHEN L.LVL = 1 THEN T.COLUMN1
7 ELSE 'This row act as separator..' END AS COLUMN1
8 FROM T CROSS JOIN (
9 SELECT LEVEL AS LVL FROM DUAL CONNECT BY LEVEL <= 2
10 ) L ORDER BY T.ROWNM, L.LVL;
ROWNM NAME TOTAL COLUMN1
---------- ---------- ----- ---------------------------
1 Jack 23
XXX XXX This row act as separator..
2 John 45
XXX XXX This row act as separator..
3 harry 2
XXX XXX This row act as separator..
4 roy 45
XXX XXX This row act as separator..
5 Jacob 26
XXX XXX This row act as separator..
10 rows selected.
SQL>

SQL Server 2008 -Missing number in sequence

I saw related questions but I really don't understand how to do this.
I have a table name "tbl_image"
id keys image_count
1 0001 1
2 0001 3
3 0001 5
4 0003 6
5 0003 9
I want my output to look like this
If I select where the keys = '0001'
output
2
4
And when I select where the keys = '0003'
output
7
8
Thanks in advance.
One method is to use recursive cte
;with cte as
(
select id, image_count,min(image_count) over (partition by Keys) cm, keys from table
union all
select id, image_count, cm+1, keys from cte c
where c.image_count > c.cm
)
select distinct c.cm as Missing from cte c
left join table t on t.keys = c.keys and t.image_count = c.cm
where c.keys = '0003' and t.image_count is null
Result :
Missing
7
8
Use recursive query
with result as
(
select min(image_count) + 1 output,
(select max(image_count) - 1 from tbl_image where keys = '0003') max_output
from tbl_image
where keys = '0003'
union all
select output + 1, max_output
from result
where output < max_output
)
select output
from result
where not exists (select 1 from tbl_image where image_count = output)
dbfiddle demo
Try this:
DECLARE #tbl_image TABLE(ID int, Keys VARCHAR(10),Image_Count INT)
INSERT INTO #tbl_image VALUES (1,'0001',1)
INSERT INTO #tbl_image VALUES (2,'0001',3)
INSERT INTO #tbl_image VALUES (3,'0001',5)
INSERT INTO #tbl_image VALUES (4,'0003',6)
INSERT INTO #tbl_image VALUES (5,'0003',9)
SELECT DISTINCT n = number
FROM Master.dbo.[spt_values]
WHERE number BETWEEN (SELECT MIN(Image_Count) FROM #tbl_image WHERE Keys='0001')
AND (SELECT MAX(Image_Count) FROM #tbl_image WHERE Keys='0001')
AND number NOT IN(SELECT Image_Count FROM #tbl_image WHERE Keys='0001')
OutPut:
2
4

how to find date difference when dates are places in different rows in same table?

I have a table::
ItemID VersionNo CreatedDate
-------------------------------
1 3 7/9/2010
1 2 7/3/2010
1 1 5/3/2010
1 0 3/3/2010
2 0 4/4/2010
3 1 4/5/2010
3 0 3/4/2010
...where Version 0 means .. its a newly produced item. Here I need to find time,(time gap between two versions) and add a column as process time.
like::
ItemID VersionNo CreatedDate ProcessTime
-------------------------------------------
1 3 7/9/2010 6Days or 6*24Hrs
1 2 7/3/2010 60Days
1 1 5/3/2010 2Days
1 0 3/3/2010 ''
2 0 4/4/2010 ''
3 1 4/5/2010 31Days
3 0 3/4/2010 ''
VersionNo's are not Fixed..means with time, it could increase... How to acheive the desire result in MS Access or in SQL-Server.
Thanks in advance for all your sincere efforts.
Thanks
How about (Access):
SELECT t.ItemID,
t.VersionNo,
t.CreatedDate, (
SELECT Top 1
CreatedDate
FROM Versions v
WHERE v.ItemID=t.ItemID
And v.VersionNo<t.VersionNo
ORDER BY VersionNo DESC) AS LastDate,
DateDiff("h",[LastDate],[CreatedDate]) AS DiffHrs,
DateDiff("d",[LastDate],[CreatedDate]) AS DiffDays
FROM Versions t
Join the table with itself, like this (SQL Server):
-- create the table and your data
create table #x (ItemID int, VersionNo int, CreatedDate datetime)
go
insert into #x
select 1, 3 ,'7/9/2010'
union all select 1 ,2 ,'7/3/2010'
union all select 1 ,1 ,'5/3/2010'
union all select 1 ,0 ,'3/3/2010'
union all select 2 ,0 ,'4/4/2010'
union all select 3 ,1 ,'4/5/2010'
union all select 3 ,0 ,'3/4/2010'
go
-- The query
select v2.ItemID, v2.VersionNo, datediff(dd, v1.CreatedDate, v2.CreatedDate)
from #x v1, #x v2
where v1.ItemID = v2.ItemID and v1.VersionNo + 1 = v2.VersionNo
Here it is in Access SQL, using 3 queries, one for each step.
Query1, self-join on itemID where versionNo is smaller:
SELECT t1.itemID, t1.versionNo, t1.created, t2.versionNo AS t2Version
FROM Table1 AS t1 INNER JOIN Table1 AS t2 ON t1.itemID = t2.itemID
WHERE (t2.versionNo)<[t1].[versionNo];
Query2, limit to max of smaller versionNos:
SELECT q1.itemID, q1.versionNo, q1.created, Max(q1.t2Version) AS MaxOft2Version
FROM Query1 AS q1
GROUP BY q1.itemID, q1.versionNo, q1.created;
Query3, now do datediff:
SELECT q2.itemID, q2.versionNo, q2.created, q2.MaxOft2Version, t1.created,
DateDiff("d",[t1].[created],[Q2].[created]) AS daysdiff
FROM Query2 AS q2 INNER JOIN Table1 AS t1
ON (q2.MaxOft2Version = t1.versionNo)
AND (q2.itemID = t1.itemID);
SQL Server 2005, to handle the case where there are gaps in VersionNo.
-- Declare a query that extends your table with a new column
-- that is the sequentially numbered representation of VersionNo.
-- This could be a view, but I used a CTE. I am going to use this
-- query twice below.
WITH Sequential AS (select *,
RANK() over (partition by ItemId order by VersionNo) as SequentialVersionNo
from #T as x
)
select
v.ItemID, v.VersionNo, v.SequentialVersionNo, v.CreatedDate,
DATEDIFF(day, vPrior.CreatedDate, v.CreatedDate) as ProcessTime
from Sequential as v
left outer join Sequential as vPrior
on v.ItemID=vPrior.ItemID
and v.SequentialVersionNo = vPrior.SequentialVersionNo+1;

How to get result from a column with combined data?

data:
id bb
1 14,35
2 5,11,12,125,36
3 3,23,45,15,1
4 651
5 5,1,6
6 1,7
For example, i wan't get id which with value '1'. So id(3,5,6) should return , but not others with '14' or '11'.
DB: Mysql
This is not the most efficient solution but it might give you what you want off the table:
select id from MyTable where bb like '%,1,%' union
select id from MyTable where bb like '1,%' union
select id from MyTable where bb like '%,1' union
select id from MyTable where bb like '1'
cheers
select * from test where find_in_set('1',bbb)
or
select * from test where bbb REGEXP '(^|,)1(,|$)'
Am I missing something?
SELECT *
FROM MyTable
WHERE (id = 3) or (id = 5) or (id = 6)
you can do like this
select * from mytable where id like '14%' or '11%'