sorting SQL with substring on string - sql

i have the data like this:
CODE_VD
N_10_19_xxx
N_0_3_xxx
N_121_131_xxx
N_100_120_xxx
N_80_90_xxx
N_20_29_xxx
as you can see i need to sort just the first number after N_,i don't know how can i get this number.
i have tried with susbsting(CODE_VD,2,3) but not exactly what i expected.
i want to get this:
CODE_VD
N_0_3_xxx
N_10_19_xxx
N_20_29_xxx
N_80_90_xxx
N_100_120_xxx
N_121_131_xxx
how can i do that ?

DECLARE #MyTable TABLE
(
CODE_VD VARCHAR(20)
)
INSERT INTO #MyTable
( CODE_VD )
VALUES
('N_10_19_xxx'),
('N_0_3_xxx'),
('N_121_131_xxx'),
('N_100_120_xxx'),
('N_80_90_xxx'),
('N_20_29_xxx');
SELECT * FROM
(
SELECT
*,
CONVERT(INT,
SUBSTRING(mt.CODE_VD,
3,
CHARINDEX('_', mt.CODE_VD, 3) - 3)) ConvCol
FROM #MyTable mt
) mt
ORDER BY mt.ConvCol
I converted to int to get the sort to work correctly, because 100 > 20

SELECT SUBSTRING(CODE_VD,3, CHARINDEX('_',CODE_VD, 3)-3)

declare #t Table (CODE_VD VARCHAR(MAX))
INSERT INTO #t (CODE_VD)VALUES ('N_10_19_xxx')
INSERT INTO #t (CODE_VD)VALUES ('N_0_3_xxx')
INSERT INTO #t (CODE_VD)VALUES ('N_121_131_xxx')
INSERT INTO #t (CODE_VD)VALUES ('N_100_120_xxx')
;WITH
sorted
AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY SUBSTRING(CODE_VD,3, CHARINDEX('_',CODE_VD, 3)-3) ORDER BY CODE_VD) AS sequence_id
FROM
#t
)
SELECT
CODE_VD
FROM
sorted
WHERE
sequence_id = 1

Related

sql query for counting the records of particular id and show in column

I have a following table:-
declare #tab table(name varchar(10),id int)
insert into #tab values ('A',1),('B',1),('C',1),('D',1),('E',2),('F',2)
I need following output:-
declare #tab1 table(name varchar(10),id int, cnt int)
insert into #tab1 values ('A',1,4),('B',1,4),('C',1,4),('D',1,4),('E',2,2),('F',2,2)
select * from #tab1
I tried following query:-
select name,id,count(*) as cnt
from #tab
group by name,id
Thanks
Try this
select name
, id
, count(*) over(partition by id) as cnt
from #tab
;
Done
;with a as
(
select Id,name, count(*) over (partition by id) cnt
from #tab
)
select Id,name,cnt
from a

How to get the each record with some condition

I have following data:
DECLARE #temp TABLE (
ID int
,sn varchar(200)
,comment varchar(2000)
,rownumber int
)
insert into #temp values(1,'sn1',NULL,1)
insert into #temp values(2,'sn1','aaa',2)
insert into #temp values(3,'sn1','bbb',3)
insert into #temp values(4,'sn1',NULL,4)
insert into #temp values(5,'sn2',NULL,1)
insert into #temp values(6,'sn2',NULL,2)
insert into #temp values(7,'sn2',NULL,3)
select * from #temp
And I want to output like this:
2 sn1 aaa 2
5 sn2 NULL 1
same sn, if comment have value, get this lower rownumber's record. For sn1, have two records with comment value, so here, get the the record with rownumber=2
If comment doesn't have value, get the lower rownumber's record. For sn2, get the record with rownumber=1
May I know how to write this SQL?
This is a prioritization query. I think row_number() is the simplest method:
select t.*
from (select t.*,
row_number() over (partition by sn
order by (case when comment is not null then 1 else 2 end),
rownumber
) as seqnum
from #temp t
) t
where seqnum = 1;
Here is a db<>fiddle.

How to use pivot for columns of type varchar

My table is:
SBType|SBName|Qty
===================
SMDB SB01 1
SMDB SB01 4
SMDB SB02 2
SMDB SB02 5
SMDB SB03 3
SMDB SB03 6
My desired output is:
SB01 | SB02 | SB03
==================
1 2 3
4 5 6
This is what my code looks like:
SELECT *
FROM (
SELECT
SM.SBName,ISNULL(ES.Qty,0)Qty
FROM RE_ES_SwitchBoard_Mast SM
left outer join RE_ES_Estimations ES on SM.PrCode=ES.PrCode and
Sm.SBType=ES.SBType and SM.SBName=ES.SBName
Where SM.PrCode='PR004' and SM.SBType='SMDB'
) as s
PIVOT
(
Max(Qty)
FOR [SBName] IN (SB01, SB02, SB03)
)AS pvthere
and the result of my attempt looks like:
SB01 SB02 SB03
1 2 3
I have tried with MAX(Qty) but it is not working.
Thanks in advance.
You are almost there.
By adding ROW_NUMBER() OVER (PARTITION BY SBName ORDER BY Qty) rn to the source of PIVOT clause you get multiple rows for different SBName instead of one grouped row. Your query should look like:
SELECT SB01, SB02, SB03
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY SB.SBName ORDER BY Qty) rn,
SB.SBName,ISNULL(ES.Qty,0) Qty
FROM RE_ES_SwitchBoard_Mast SM
left outer join RE_ES_Estimations ES on SM.PrCode=ES.PrCode and
Sm.SBType=ES.SBType and SM.SBName=ES.SBName
Where SM.PrCode='PR004' and SM.SBType='SMDB'
) as s
PIVOT
(
Max(Qty)
FOR [SBName] IN (SB01, SB02, SB03)
)AS pvthere
A verifiable example here:
CREATE TABLE #sample
(
SBType varchar(MAX),
SBName varchar(MAX),
Qty int
)
INSERT INTO #sample VALUES ('SMDB','SB01',1)
INSERT INTO #sample VALUES ('SMDB','SB01',4)
INSERT INTO #sample VALUES ('SMDB','SB02',2)
INSERT INTO #sample VALUES ('SMDB','SB02',5)
INSERT INTO #sample VALUES ('SMDB','SB03',3)
INSERT INTO #sample VALUES ('SMDB','SB03',6)
SELECT SB01, SB02, SB03
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY SBName ORDER BY Qty) rn, SBName,ISNULL(Qty,0) Qty
FROM #sample
) as s
PIVOT
(
Max(Qty)
FOR [SBName] IN (SB01, SB02, SB03)
) AS pvthere
DROP TABLE #sample
Dynamic query is the only way to use varchar columns in pivot. Have a look at below code to get idea.
First step is to generate comma separated list of items for column you need to use in pivot.
Then you can use this generated list in dynamic query for pivot columns.
Note: For example purpose I have used temp table. Replace it with your actual table.
CREATE TABLE #temptable
(
SBType VARCHAR(20),
SBName VARCHAR(20),
Qty INT
)
INSERT INTO #temptable SELECT 'SMDB','SB01',1
INSERT INTO #temptable SELECT 'SMDB','SB01',4
INSERT INTO #temptable SELECT 'SMDB','SB02',2
INSERT INTO #temptable SELECT 'SMDB','SB02',5
INSERT INTO #temptable SELECT 'SMDB','SB03',3
INSERT INTO #temptable SELECT 'SMDB','SB03',6
SELECT * FROM #temptable
DECLARE #cols AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(SBName)
from #temptable
group by SBName
order by SBName
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #cols
DECLARE #query NVARCHAR(MAX)
SET #query = '
SELECT *
FROM
(
SELECT SBType,SBName,Qty,
row_number() over (partition by SBName order by Qty) as rn
FROM #temptable
) src
PIVOT
(
MIN(Qty)
FOR SBName IN (' + #cols + ')
) piv;'
EXEC(#query)
DROP TABLE #temptable

Get records with more than one value and at least one of them is zero

Create table #Tbl
(
ID int not null,
Keyword nvarchar(max)
)
Insert into #Tbl Values ('0','Cryptography')
Insert into #Tbl Values ('1','Cryptography')
Insert into #Tbl Values ('4','Cryptography')
Insert into #Tbl Values ('0','SQL')
Insert into #Tbl Values ('0','SQL')
Insert into #Tbl Values ('3','Cloud Computing')
Insert into #Tbl Values ('6','Recursion')
Insert into #Tbl Values ('8','Recursion')
Insert into #Tbl Values ('0','Universe')
Insert into #Tbl Values ('0','Universe')
Insert into #Tbl Values ('7','Universe')
I need to get the titles which has more than one ID and at least one of the ID is zero.
So the expected result will be:
Cryptography
Universe
I tried below query but not able to add "at least one id is zero" condition
select Keyword,COUNT(distinct id) from #Tbl
group by Keyword
having COUNT(distinct id)>1
How can I proceed here ? Thanks for your help.
Assuming your IDs start from 0, the below should work
select Keyword,COUNT(distinct id) from #Tbl
group by Keyword
having COUNT(distinct id)>1 and MIN(id) = 0
There are many ways to do this, one example:
SELECT DISTINCT Keyword
FROM #Tbl T
WHERE EXISTS (SELECT 1 FROM #Tbl WHERE Keyword = T.Keyword
AND ID = 0)
AND EXISTS (SELECT 1 FROM #Tbl WHERE Keyword = T.Keyword
AND ID != 0)
Here is a sqlfiddle with a demo.
This should do it:
SELECT Keyword
FROM #Tbl
WHERE Keyword IN (SELECT DISTINCT Keyword FROM #Tbl WHERE ID = 0)
GROUP BY Keyword
HAVING COUNT(DISTINCT id) > 1
Here's yet another approach:
SELECT Keyword, COUNT(DISTINCT ID)
FROM #Tbl
GROUP BY Keyword
HAVING COUNT(DISTINCT ID) > ALL (SELECT COUNT(DISTINCT NULLIF(ID, 0)) UNION ALL SELECT 1)
;

transact-sql question

Assume there were 100 records in tableA and tableA contained a column named 'price'.
How do I select the first-n record if where sum of price > a certain amount (e.g. 1000) without using cursor?
thanks
Top N implies some kind of order, which you did not supply, so I assumed any random order.
You can change this on the OVER clause of the ROW_NUMBER().
Try something like
DECLARE #Table TABLE(
Price FLOAT
)
INSERT INTO #Table SELECT 1
INSERT INTO #Table SELECT 11
INSERT INTO #Table SELECT 12
INSERT INTO #Table SELECT 15
INSERT INTO #Table SELECT 10
INSERT INTO #Table SELECT 65
INSERT INTO #Table SELECT 100
DECLARE #TotalPrice FLOAT
SELECT #TotalPrice = 100
;WITH Vals AS (
SELECT *,
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) RNR
FROM #Table
)
, Totals AS (
SELECT v.RNR,
SUM(vP.Price) TotalPrice
FROM Vals v LEFT JOIN
Vals vP ON v.RNR >= vP.RNR
GROUP BY v.RNR
)
, LimitValue AS (
SELECT TOP 1
RNR
FROM Totals
WHERE TotalPrice >= #TotalPrice
ORDER BY RNR
)
SELECT *
FROM Vals
WHERE RNR <= (
SELECT RNR
FROM LimitValue
)
select price from tableA
where price > 1000
limit n;
n - no. of records you want in result set
--
Cheers