Avoid calling twice to the same nested query - sql-server

I am trying to run this query:
select productID,t.[year]
from (
select ProductID, [year] = year(DT), howMuch = count(*)
from [CONTAINS] as c
join ORDERS as o on c.OrderID = o.OrderID
group by ProductID, year(DT)
) as t
where howMuch >= all (
select howMuch
from (
select ProductID, [year] = year(DT), howMuch = count(*)
from [CONTAINS] as c
join ORDERS as o on c.OrderID = o.OrderID
group by ProductID,year(DT)
) as k
where t.[year] = k.[year]
)
Well, it works. but I want to avoid using the same select query twice. What do you suggest me to do?

It seems your database is SQL Server. If this is the case, you can use a CTE (Common Table Expression), something that was designed for this case.
Your query can be nicely simplified to:
with
q as (
select ProductID, [year]=year(DT),howMuch=count(*)
from [CONTAINS] as c join ORDERS as o on c.OrderID=o.OrderID
group by ProductID,year(DT)
)
select productID, t.[year]
from q as t
where howMuch >= all (
select howMuch from q as k where t.[year]=k.[year]
)

Related

Single-row subquery returns more than one row - Issue in table conversion in snowflake

I am having a issue related to Snowflake. When I run the below query, I do get 'Single-row subquery returns more than one row.'
Do you have any idea on how to fix this issue?
Below is the query
SELECT DISTINCT J.JOB_ID , J.ACCEPTED_DATE ,
(SELECT DOCUMENT_ID FROM (SELECT DD.DOCUMENT_ID ,row_number() over (partition by DD.DOCUMENT_ID order by DD.DOCUMENT_ID ) as row_number
FROM SFG.RCM_JOB_INDUSTRY DD
LEFT JOIN USERS_L.JOB_MASTER J ON DD.JOB_ID = J.JOB_ID) WHERE row_number=1) AS DOCUMENT_ID,
(SELECT U.USERNAME FROM SFL.RCS_USER U LEFT JOIN SMW.RCS_STATUS RS ON RS.USER_ID = U.USER_ID) AS REPAIRED_BY
FROM USERS_L.JOB_MASTER J
Thank you
There are 2 subqueries, and I suspect the second one causing the issue:
SELECT
DISTINCT J.JOB_ID,
J.ACCEPTED_DATE,
(
SELECT
DOCUMENT_ID
FROM
(
SELECT
DD.DOCUMENT_ID,
row_number() over (
partition by DD.DOCUMENT_ID
order by
DD.DOCUMENT_ID
) as row_number
FROM
SFG.RCM_JOB_INDUSTRY DD
LEFT JOIN USERS_L.JOB_MASTER J ON DD.JOB_ID = J.JOB_ID
)
WHERE
row_number = 1
) AS DOCUMENT_ID,
(
SELECT
TOP 1 U.USERNAME
FROM
SFL.RCS_USER U
LEFT JOIN SMW.RCS_STATUS RS ON RS.USER_ID = U.USER_ID
) AS REPAIRED_BY
FROM
USERS_L.JOB_MASTER J
https://docs.snowflake.com/en/sql-reference/constructs/top_n.html

query is not returning distinct record

Hi can you please take a look why my query is not returning distinct record. i want result with following condition OE1='SCHEDCHNG', need only recent records per orderid or ordernum means only one record per ordernum or orderid and also dropdate is null. My query is as below
select DISTINCT TOP 100 OE.ORDERID,OE.ID,OE.ORDERNUM,OE.OE4 from OrderExports OE
inner join (
select ORDERNUM, max(OE4) as MaxDate
from OrderExports
group by ORDERNUM
) tm
on OE.ORDERNUM = tm.ORDERNUM and OE.OE4 = tm.MaxDate
inner join orde_ O on OE.ORDERID = O.ORDERID
WHERE OE1='SCHEDCHNG' AND O.DROPDATE is null
Pretty sparse on details here but I think you are wanting something along these lines.
with SortedResults as
(
select OE.ORDERID
, OE.ID
, OE.ORDERNUM
, OE.OE4
, ROW_NUMBER() over(partition by OE.ORDERID, OE.ORDERNUM order by OE.OE4 desc) as RowNum
from OrderExports OE
inner join
(
select ORDERNUM
, max(OE4) as MaxDate
from OrderExports
group by ORDERNUM
) tm on OE.ORDERNUM = tm.ORDERNUM and OE.OE4 = tm.MaxDate
inner join orde_ O on OE.ORDERID = O.ORDERID
WHERE OE1='SCHEDCHNG'
AND O.DROPDATE is null
)
select ORDERID
, ID
, ORDERNUM
, OE4
from SortedResults
where RowNum = 1
You can try using max and group by as below :
SELECT a.ID, max(a.ORDERID) as OrderID, max(a.ORDERNUM) as OrderNum,MAX(OE.OE4) as OE4 FROM
(
--your query
) a
group by a.ID

How to list duplicate records?

I have the following table structure:
id|date|studenttypeid|name|audituser
1|.....|4|Jason|....
2|.....|4|Robin|....
3|.....|4|Jason|....
4|.....|4|Dan|....
5|.....|4|Robin|....
I need to list all records which are duplicates on studenttypeid + name.
With the above data, the query should give me the following output:
1|.....|4|Jason|....
2|.....|4|Robin|....
3|.....|4|Jason|....
5|.....|4|Robin|....
How can I achieve this on SQL Server 2008?
You can use a group by and then join back to the original table, like this:
WITH Temp(StudentTypeId, Name) AS(
SELECT
StudentTypeId, Name
FROM YourTable
GROUP BY
StudentTypeId, Name
HAVING Count(1) > 1
)
SELECT YourTable.*
FROM YourTable
INNER JOIN Temp
ON YourTable.StudentTypeId = Temp.StudentTypeId
AND YourTable.Name = Temp.Name
you can use ROW_NUMBER()
SELECT ID, DATE, studenttypeid, name, audituser
FROM
(
SELECT ID, DATE, studenttypeid, name, audituser,
ROW_NUMBER() OVER (PARTITION BY studenttypeid, name
ORDER BY id) rn
FROM yourTableName
) a
WHERE rn = 1
SQLFiddle Demo
If you want to include every occurrence of the duplicates, some more methods using CROSS APPLY...
SELECT p.*
FROM people p
CROSS APPLY (
SELECT TOP(1) * FROM people p2 WHERE p2.ID <> p.ID AND p2.name = p.name AND p.studenttypeid = p2.studenttypeid
) as pWithDups
Or an EXISTS check
SELECT p.*
FROM people p
WHERE EXISTS (
SELECT *
FROM people p2
WHERE p2.ID <> p.ID AND p2.name = p.name AND p.studenttypeid = p2.studenttypeid
)
Try this
SELECT a.*
FROM yourtable a
JOIN (SELECT studenttypeid,
name
FROM yourtable
GROUP BY studenttypeid,
name
HAVING Count(studenttypeid) > 1) b ON b.name = a.name
ORDER BY a.id

How to use CROSS APPLY in this scenario

I have a ProductStatus table as listed below. I need to list all products whose latest status is “SU”. Along with that I need to list what was the previous status of this product.
Based on referring various posts, it seems like CROSS APPLY will be suitable for this. I made an attempt as listed below but that didn’t give the expected result.
What is the best way to achieve this in SQL Server 2005 (without using subquery)?
DECLARE #ProductStatus TABLE (ProductStatusID INT, productCode VARCHAR(5), statusCode VARCHAR(2))
INSERT INTO #ProductStatus
SELECT 1,'10011','RE' --Recevied
UNION
SELECT 2,'10011','SU' --Suspended
UNION
SELECT 3,'10012','IT' -- In Transit
UNION
SELECT 4,'10012','RE' -- Received
UNION
SELECT 10,'10012','PR' -- Produced
UNION
SELECT 12,'10012','SU' -- Suspended
UNION
SELECT 14,'10013','RE' -- Recevied
UNION
SELECT 16,'10014','SU' -- Recevied
UNION
SELECT 18,'10014','RE' -- Recevied
CROSS APPLY attempt
SELECT *
FROM #ProductStatus P
CROSS APPLY
(
SELECT MAX(V.ProductStatusID) as maxVal
FROM #ProductStatus V
WHERE V.ProductCode = P.ProductCode
AND V. ProductStatusID < P.ProductStatusID
GROUP BY V.ProductCode
)ML
WHERE P.statusCode = 'SU'
EXPECTED RESULT
You can do this with cross apply but I think row_number() is an easier approach:
select ProductCode,
max(case when seqnum = 1 then statusCode end) as LastStatus,
max(case when seqnum = 2 then statusCode end) as PrevStatus
from (select p.*,
row_number() over (partition by ProductCode order by ProductStatusId desc) as seqnum
from #ProductStatus p
) p
group by ProductCode
having max(case when seqnum = 1 then statusCode end) = 'SU';
Lijo, I've structured it as a CTE so you can see how I've developed my ideas. You can refactor it as sub-queries without affecting the meaning if you are more comfortable with those.
;with MostRecentStatus as (
select
MAX(ProductStatusID) as ProductStatusID,
productCode
from #ProductStatus as p1
group by productCode
)
,MostRecentIsSU as (
select
p2.ProductStatusID,
p2.productCode,
p2.statusCode
from MostRecentStatus as mrs
inner join #ProductStatus as p2
on p2.ProductStatusID = mrs.ProductStatusID
and p2.statusCode = 'SU'
)
select
m.ProductStatusID,
m.productCode,
m.statusCode,
p3.statusCode as PrevStatus,
p3.ProductStatusID as PrevProductStatusID
from MostRecentIsSU as m
left outer join #ProductStatus as p3
on p3.productCode = m.productcode
and p3.ProductStatusID = m.ProductStatusID - 1;
Edit: ..and here's the ROW_NUMBER() version with kudos to #attila.
;with InSquence as
(
select
ProductStatusID,
productCode,
statusCode,
ROW_NUMBER() OVER(PARTITION BY productCode ORDER BY ProductStatusID desc) as Sequence
from #ProductStatus
)
,FirstIsSU as
(
select
ProductStatusID,
productCode
from InSquence
where Sequence = 1
and statusCode = 'SU'
)
,PreviousCode as
(
select
ProductStatusID,
productCode,
statusCode
from InSquence
where Sequence = 2
)
select
f.ProductStatusID,
f.productCode,
'SU' as CurrentStatus,
p.statusCode as PrevStatus,
p.ProductStatusID as PrevProductStatusID
from FirstIsSU as f
left outer join PreviousCode as p
on p.productCode = f.ProductCode;
Here is a convoluted solution which serves mainly to illustrate that this should probably be done using row_number() :)
SELECT
F.productCode, F.statusCode, F.productStatusID, F.PriorProductStatusID, PriorStatus.statusCode
FROM
(
SELECT
PCS.productCode, PCS.statusCode, PCS.productStatusID, MAX(PS.productStatusID) PriorProductStatusID
FROM
(
SELECT productCode, MAX(productStatusID) productStatusID
FROM #ProductStatus
GROUP BY productCode
) LatestStatus
INNER JOIN
#ProductStatus PCS
ON PCS.productCode = LatestStatus.productCode
AND PCS.productStatusID = LatestStatus.productStatusID
AND PCS.statusCode = 'SU'
LEFT OUTER JOIN
#ProductStatus PS
ON PS.productCode = PCS.productCode
AND PS.productStatusID < PCS.productStatusID
GROUP BY PCS.productCode, PCS.statusCode, PCS.productStatusID
) F
LEFT OUTER JOIN
#ProductStatus PriorStatus
ON F.productCode = PriorStatus.productCode
AND F.PriorProductStatusID = PriorStatus.ProductStatusID

Table Group By - Tsql -

alt text http://img187.imageshack.us/img187/8453/testhc3.png
alt text http://img145.imageshack.us/img145/3306/test2bn4.png
The first picture is my query. I need to obtain results in second picture.
select OrarioA, OrarioB, MAX(VW_DettaglioOrariLinee_FromAToB.IDOrario), dbo.VW_DettaglioOrariLinee_FromAToB.IDDettaglioOrarioA, dbo.VW_DettaglioOrariLinee_FromAToB.IDDettaglioOrarioB
FROM dbo.VW_DettaglioOrariLinee_FromAToB INNER JOIN
Tb_Linee ON dbo.VW_DettaglioOrariLinee_FromAToB.IDRelA = Tb_Linee.IDRelA AND
dbo.VW_DettaglioOrariLinee_FromAToB.IDRelB = Tb_Linee.IDRelB INNER JOIN
dbo.periodi ON dbo.VW_DettaglioOrariLinee_FromAToB.IDOrario = dbo.periodi.IDOrario INNER JOIN
dbo.relgiornisettimanaorarilinee ON dbo.VW_DettaglioOrariLinee_FromAToB.IDOrario = dbo.relgiornisettimanaorarilinee.IDOrario
This is my real query:
WITH Tb_Linee AS
(
SELECT * FROM VW_rellineestazionamenti
WHERE
IDLINEA = #IDLINEA
AND
IDStazA = #IDStazA
AND
IDStazB = #IDStazB
AND
PosizioneA = #PosizioneA
AND
PosizioneB = #PosizioneB
)
select OrarioA, OrarioB, VW_DettaglioOrariLinee_FromAToB.IDOrario, dbo.VW_DettaglioOrariLinee_FromAToB.IDDettaglioOrarioA, dbo.VW_DettaglioOrariLinee_FromAToB.IDDettaglioOrarioB
FROM dbo.VW_DettaglioOrariLinee_FromAToB INNER JOIN
Tb_Linee ON dbo.VW_DettaglioOrariLinee_FromAToB.IDRelA = Tb_Linee.IDRelA AND
dbo.VW_DettaglioOrariLinee_FromAToB.IDRelB = Tb_Linee.IDRelB INNER JOIN
dbo.periodi ON dbo.VW_DettaglioOrariLinee_FromAToB.IDOrario = dbo.periodi.IDOrario INNER JOIN
dbo.relgiornisettimanaorarilinee ON dbo.VW_DettaglioOrariLinee_FromAToB.IDOrario = dbo.relgiornisettimanaorarilinee.IDOrario
If you want to partition by OrarioA only:
SELECT OrarioA, OrarioB, IDOrario, IDDettaglioOrarioA, IDDettaglioOrarioB
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY OrarioA ORDER BY OrarioB DESC, IDOrario DESC) AS rn
FROM table
) t
WHERE rn = 1
, this will result in the resultset as on picture 2.
If you want to partition by OrarioA and OrarioB:
SELECT OrarioA, OrarioB, IDOrario, IDDettaglioOrarioA, IDDettaglioOrarioB
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY OrarioA, OrarioB ORDER BY IDOrario DESC) AS rn
FROM table
) t
WHERE rn = 1
, but this won't filter out the first row in your resultset.
From the data you explained in your screenshots, I understand it as you need the id fields for the most highest IDOrario grouped by OrarioA and OrarioB?
SELECT IDDettaglioOrarioA, IDDettaglioOrarioB
FROM TABLE
GROUP BY
OrarioA, OrarioB
ORDER BY IDOrario DESC
If you need to select more columns, select any more at will.

Resources