How can I exclude a column row number from distinct?
The select statement looks like this:
SELECT *
FROM
(SELECT DISTINCT TOP 100
ROW_NUMBER() OVER (ORDER BY Cases.CreatedDate DESC) as row,
Cases.status, Cases.CreatedDate, Cases.DWFCaseId,
Resource.ResourceInfo AS ResourceFullName,
actions.ActionDate, Action.ActionDuedate
FROM
Cases
INNER JOIN
ResourceInfo ON Cases.caseid = ResourceInfo.caseid
LEFT OUTER JOIN
actions ON actions.ActionId = ResourceInfo.ActionId
WHERE
(actions.ActionType = 2)
)
Use the window function in the outer query instead of the subquery as
SELECT *,
ROW_NUMBER() OVER (ORDER BY CreatedDate DESC) as row,
FROM
(
SELECT DISTINCT TOP 100
Cases.status,
Cases.CreatedDate,
Cases.DWFCaseId,
Resource.ResourceInfo AS ResourceFullName,
actions.ActionDate,
Action.ActionDuedate
FROM
Cases
INNER JOIN
ResourceInfo ON Cases.caseid = ResourceInfo.caseid
LEFT OUTER JOIN
actions ON actions.ActionId = ResourceInfo.ActionId
WHERE actions.ActionType = 2
) T; --Don't forget to use an alias for the subquery
Take it out from subquery:
select ROW_NUMBER() OVER (ORDER BY x.CreatedDate desc ) as row, x.*
from (
SELECT DISTINCT top (100)
Cases.status,
Cases.CreatedDate,
Cases.DWFCaseId,
Resource.ResourceInfo AS ResourceFullName,
actions.ActionDate,
Action.ActionDuedate
from Cases
inner join ResourceInfo on Cases .caseid = ResourceInfo .caseid
left outer join actions on actions.ActionId = ResourceInfo .ActionId
WHERE (actions.ActionType = 2)
) x
Related
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
I have created a table in html to display first rows of each id and allow user to select specific range they want to see, but not sure how I can write it in query.
With results as
(
i.*,
ROW_NUMBER() OVER (PARTITION BY i.ID ORDER BY I.ID DESC) AS [RN]
FROM HolidayList AS I
INNER JOIN (
SELECT ID, MIN(CreateDate) FROM HolidayList GROUP BY ID
)
AS j ON i.ID = j.ID AND i.CreateDate = j.CreateDate
)
SELECT * FROM results WHERE [RN] = 1;
UPDATED
I have tried to inject two ROW_NUMBER(), but what I received is row 10 and row 25 and they are first rows of some specific id.
With results as
(
i.*,
ROW_NUMBER() OVER (PARTITION BY i.ID ORDER BY I.ID DESC) AS [RN],
ROW_NUMBER() OVER (ORDER BY I.ID) AS [R]
FROM HolidayList AS I
INNER JOIN (
SELECT ID, MIN(CreateDate) FROM HolidayList GROUP BY ID
)
AS j ON i.ID = j.ID AND i.CreateDate = j.CreateDate
)
SELECT * FROM results WHERE [RN] = 1 AND BETWEEN [R]>10 AND [R]<25
What I am really looking for is select a specific range from all the first row for each id.
FINAL
Thank to McGlothlin, finally I solve it. What I need is a nested CTE.
With First_CTE as
(
i.*,
ROW_NUMBER() OVER (PARTITION BY i.ID ORDER BY I.ID DESC) AS [RN]
FROM HolidayList AS I
INNER JOIN (
SELECT ID, MIN(CreateDate) FROM HolidayList GROUP BY ID
)
AS j ON i.ID = j.ID AND i.CreateDate = j.CreateDate
),
results AS
(
SELECT k.*,
ROW_NUMBER() OVER (ORDER BY k.ID DESC) AS [R]
FROM First_CTE AS k WHERE k.[RN] = 1
)
SELECT * FROM results WHERE [R]>10 AND [R]<25
The problem lies in this line:
ROW_NUMBER() OVER I.ID AS [R]
I think what you meant was:
ROW_NUMBER() OVER (ORDER BY I.ID) AS [R]
This is assuming you want to give it a row count over every row that is returned in the CTE. The ROW_NUMBER() function requires an ORDER BY to be specified, and the OVER clause would still require parentheses if you were using a function like SUM that could be used without an ORDER BY.
Edit: Based on your comment, it sounds like what you're looking for is an OFFSET. In that case you would remove the second ROW_NUMBER and include something like this:
ORDER BY ID OFFSET 10 ROWS FETCH FIRST 15 ROWS ONLY
This returns rows 11 to 25, sorted by ID.
Since the OFFSET syntax doesn't work in SQL Server 2008, you should do something like this as your end result:
With results as
(
i.*,
ROW_NUMBER() OVER (PARTITION BY i.ID ORDER BY I.ID DESC) AS [RN]
ROW_NUMBER() OVER (ORDER BY I.ID) AS [R]
FROM HolidayList AS I
INNER JOIN (
SELECT ID, MIN(CreateDate) FROM HolidayList GROUP BY ID
)
AS j ON i.ID = j.ID AND i.CreateDate = j.CreateDate
)
SELECT *
FROM results
WHERE [RN] = 1
AND [R] BETWEEN 11 AND 25
I have this query:
SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY CASE WHEN ISNUMERIC(dtLu.sLu) = 1 THEN CONVERT(INT, dtLu.sLu) ELSE 9999999 END asc, dtLu.sLu) as row,
dtLu.*, dtLuDerived.cCll, dtMtrDerived.cMtrCll, dtMtrDerived.cMtrCllIn, dtMtrDerived.cMtrCllOut FROM dtLu
LEFT OUTER JOIN (
SELECT pLu, COUNT(pLu) AS cCll
FROM dtCll
GROUP BY pLu)
AS dtLuDerived ON dtLu.pLu = dtLuDerived.pLu
LEFT OUTER JOIN (
SELECT dtCll.pLu, SUM(cMtrCll) AS cMtrCll, SUM(cMtrCllIn) AS cMtrCllIn, SUM(cMtrCllOut) AS cMtrCllOut
FROM dtMtrCll
INNER JOIN dtCll on dtCll.pCll = dtMtrCll.pCll
WHERE dtCll.pWhr IN (SELECT DISTINCT pWhr FROM dtUserWhr WHERE pUser = 5)
GROUP BY dtCll.pLu)
AS dtMtrDerived ON dtLu.pLu = dtMtrDerived.pLu
INNER JOIN dtLct on dtLct.pLct = dtLu.pLct
WHERE dtLu.pLu > 0 AND dtLct.pLctAsl IN (select pAsl from dtAsl where pAslUnt = 1)
-- this is the ORDER I need
ORDER BY dtLu.pLct DESC
) a
WHERE a.row > 0 and a.row <= 17
but if I use the order ORDER BY dtLu.pLct DESC it gives me error...
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP, OFFSET
or FOR XML is also specified.
I searched, found various samples, but my subquery is different, 'cause is needed to retrieve only 17 rows per page (next page will have the last line like this: WHERE a.row > 17 and a.row <=35)
how can I select the top 17 rows but with an order inside?
thanks
You are trying to put the order in your inner query which doesn't work. Move the order by to the main query. Also, you should list your columns instead of using *. You could probably improved this query a bit with fewer subselects but that is outside the scope of your question.
SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY CASE WHEN ISNUMERIC(dtLu.sLu) = 1 THEN CONVERT(INT, dtLu.sLu) ELSE 9999999 END asc, dtLu.sLu) as row,
dtLu.* --you should list the columns out here
, dtLuDerived.cCll, dtMtrDerived.cMtrCll, dtMtrDerived.cMtrCllIn, dtMtrDerived.cMtrCllOut FROM dtLu
LEFT OUTER JOIN (
SELECT pLu, COUNT(pLu) AS cCll
FROM dtCll
GROUP BY pLu)
AS dtLuDerived ON dtLu.pLu = dtLuDerived.pLu
LEFT OUTER JOIN (
SELECT dtCll.pLu, SUM(cMtrCll) AS cMtrCll, SUM(cMtrCllIn) AS cMtrCllIn, SUM(cMtrCllOut) AS cMtrCllOut
FROM dtMtrCll
INNER JOIN dtCll on dtCll.pCll = dtMtrCll.pCll
WHERE dtCll.pWhr IN (SELECT DISTINCT pWhr FROM dtUserWhr WHERE pUser = 5)
GROUP BY dtCll.pLu)
AS dtMtrDerived ON dtLu.pLu = dtMtrDerived.pLu
INNER JOIN dtLct on dtLct.pLct = dtLu.pLct
WHERE dtLu.pLu > 0 AND dtLct.pLctAsl IN (select pAsl from dtAsl where pAslUnt = 1)
-- this is the ORDER I need
--ORDER BY dtLu.pLct DESC
) a
WHERE a.row > 0 and a.row <= 17
order by a.pLct
Use TOP 100 Percent in Subquery
SELECT *
FROM (SELECT top 100 percent Row_number()
OVER (
ORDER BY CASE WHEN Isnumeric(dtLu.sLu) = 1 THEN CONVERT(INT, dtLu.sLu) ELSE 9999999 END ASC, dtLu.sLu) AS row,
dtLu.*,
dtLuDerived.cCll,
dtMtrDerived.cMtrCll,
dtMtrDerived.cMtrCllIn,
dtMtrDerived.cMtrCllOut
FROM dtLu
LEFT OUTER JOIN (SELECT pLu,
Count(pLu) AS cCll
FROM dtCll
GROUP BY pLu) AS dtLuDerived
ON dtLu.pLu = dtLuDerived.pLu
LEFT OUTER JOIN (SELECT dtCll.pLu,
Sum(cMtrCll) AS cMtrCll,
Sum(cMtrCllIn) AS cMtrCllIn,
Sum(cMtrCllOut) AS cMtrCllOut
FROM dtMtrCll
INNER JOIN dtCll
ON dtCll.pCll = dtMtrCll.pCll
WHERE dtCll.pWhr IN (SELECT DISTINCT pWhr
FROM dtUserWhr
WHERE pUser = 5)
GROUP BY dtCll.pLu) AS dtMtrDerived
ON dtLu.pLu = dtMtrDerived.pLu
INNER JOIN dtLct
ON dtLct.pLct = dtLu.pLct
WHERE dtLu.pLu > 0
AND dtLct.pLctAsl IN (SELECT pAsl
FROM dtAsl
WHERE pAslUnt = 1)
-- this is the ORDER I need
ORDER BY dtLu.pLct DESC) a
WHERE a.row > 0
AND a.row <= 17
I want to use left outer join like this:
SELECT ...
FROM Table1
LEFT OUTER JOIN
(SELECT only e.g. 3rd record... , SomeField FROM Table2) tbl2
ON Table1.SomeField = tbl2.SomeField
How can I do that, if I need the subquery to select not just the 3rd record from Table2, but the 3rd record among the Table2 records that have SomeField = Table1.SomeField?
Thanks.
If this is sql server 2005 or newer, you might use row_number():
LEFT JOIN
(
select *
from
(
select *,
row_number() over (order by something) rn
from Table2
where Table2.Column = Table1.Column
) a
where a.rn = 3
) a
Unfortunately you need to nest it a level deeper because you cannot use row_number in a condition directly.
EDIT:
My bad - i didn't really notice the join part. If you want to join derived table, use this:
LEFT JOIN
(
select *,
row_number() over (partition by SomeField order by something) rn
from Table2
) tbl2
ON Table1.SomeField = tbl2.SomeField
AND tbl2.rn = 3
Note: you need ORDER BY in row_number() to keep things consistent.
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.