I want to calculate the days between 2 dates on multiple entries but I have this error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I'm trying to use a LAG() but I can't find a solution.
[Data to read]
(https://i.stack.imgur.com/L7X35.png)
SELECT DATEDIFF(
DAY,
(SELECT DATEFROMPARTS(dat.year, dat.month, dat.day)
FROM FactReport
JOIN DimDate AS dat ON dat.id = factReport.updatedDateId
WHERE bugId IN (
SELECT bugid FROM FactReport
GROUP BY bugid HAVING count(*) > 1)),
LAG(
(SELECT DATEFROMPARTS(dat.year, dat.month, dat.day)
FROM FactReport
JOIN DimDate AS dat ON dat.id = factReport.updatedDateId
WHERE bugId IN (
SELECT bugid FROM FactReport
GROUP BY bugid HAVING count(*) > 1)
))
OVER (ORDER BY FactReport.bugid))
as TimeToUpdate
FROM FactReport
Related
-- FIRST LOGIN DATE
WITH CTE_FIRST_LOGIN AS
(
SELECT
PLAYER_ID, EVENT_DATE,
ROW_NUMBER() OVER (PARTITION BY PLAYER_ID ORDER BY EVENT_DATE ASC) AS RN
FROM
ACTIVITY
),
-- CONSECUTIVE LOGINS
CTE_CONSEC_PLAYERS AS
(
SELECT
PLAYER_ID,
LEAD(EVENT_DATE,1) OVER (PARTITION BY EVENT_DATE ORDER BY EVENT_DATE) NEXT_DATE
FROM
ACTIVITY A
JOIN
CTE_FIRST_LOGIN C ON A.PLAYER_ID = C.PLAYER_ID
WHERE
NEXT_DATE = DATEADD(DAY, 1, A.EVENT_DATE) AND C.RN = 1
GROUP BY
A.PLAYER_ID
)
-- FRACTION
SELECT
NULLIF(ROUND(1.00 * COUNT(CTE_CONSEC.PLAYER_ID) / COUNT(DISTINCT PLAYER_ID), 2), 0) AS FRACTION
FROM
ACTIVITY
JOIN
CTE_CONSEC_PLAYERS CTE_CONSEC ON CTE_CONSEC.PLAYER_ID = ACTIVITY.PLAYER_ID
I am getting the following error when I run this query.
[42S22] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Invalid column name 'NEXT_DATE'. (207) (SQLExecDirectW)
This is a leetcode medium question 550. Game Play Analysis IV. I wanted to know why it can't identify the column NEXT_DATE here and what am I missing? Thanks!
The problem is in this CTE:
-- CONSECUTIVE LOGINS prep
CTE_CONSEC_PLAYERS AS (
SELECT
PLAYER_ID,
LEAD(EVENT_DATE,1) OVER (PARTITION BY EVENT_DATE ORDER BY EVENT_DATE) NEXT_DATE
FROM ACTIVITY A
JOIN CTE_FIRST_LOGIN C ON A.PLAYER_ID = C.PLAYER_ID
WHERE NEXT_DATE = DATEADD(DAY, 1, A.EVENT_DATE) AND C.RN = 1
GROUP BY A.PLAYER_ID
)
Note that you are creating NEXT_DATE as a column alias in this CTE but also referring to it in the WHERE clause. This is invalid because by SQL clause-ordering rules the NEXT_DATE column alias does not exist until you get to the ORDER BY clause which is the last evaluated clause in a SQL query or subquery. You don't have an ORDER BY clause in this subquery, so technically the NEXT_DATE column alias only exists to [sub]queries that both come after and reference your CTE_CONSEC_PLAYERS CTE.
To fix this you'd probably want two CTEs like this (untested):
-- CONSECUTIVE LOGINS
CTE_CONSEC_PLAYERS_pre AS (
SELECT
PLAYER_ID,
RN,
EVENT_DATE,
LEAD(EVENT_DATE,1) OVER (PARTITION BY EVENT_DATE ORDER BY EVENT_DATE) NEXT_DATE
FROM ACTIVITY A
JOIN CTE_FIRST_LOGIN C ON A.PLAYER_ID = C.PLAYER_ID
)
-- CONSECUTIVE LOGINS
CTE_CONSEC_PLAYERS AS (
SELECT
PLAYER_ID,
MAX(NEXT_DATE) AS NEXT_DATE,
FROM CTE_CONSEC_PLAYERS_pre
WHERE NEXT_DATE = DATEADD(DAY, 1, EVENT_DATE) AND RN = 1
GROUP BY PLAYER_ID
)
You gave every table an alias (for example JOIN CTE_FIRST_LOGIN C has the alias C), and every column access is via the alias. You need to add the correct alias from the correct table to NEXT_DATE.
Your primary issue is that NEXT_DATE is a window function, and therefore cannot be referred to in the WHERE because of SQL's order of operations.
But it seems this query is over-complicated.
The problem to be solved appears to be: how many players logged in the day after they first logged in, as a percentage of all players.
This can be done in a single pass (no joins), by using multiple window functions together:
WITH CTE_FIRST_LOGIN AS (
SELECT
PLAYER_ID,
EVENT_DATE,
ROW_NUMBER() OVER (PARTITION BY PLAYER_ID ORDER BY EVENT_DATE) AS RN,
-- if EVENT_DATE is a datetime and can have multiple per day then group by CAST(EVENT_DATE AS date) first
LEAD(EVENT_DATE, 1) OVER (PARTITION BY EVENT_DATE ORDER BY EVENT_DATE) AS NextDate
FROM ACTIVITY
),
BY_PLAYERS AS (
SELECT
c.PLAYER_ID,
SUM(CASE WHEN c.RN = 1 AND c.NextDate = DATEADD(DAY, 1, c.EVENT_DATE)
THEN 1 END) AS IsConsecutive
FROM CTE_FIRST_LOGIN AS c
GROUP BY c.PLAYER_ID
)
SELECT ROUND(
1.00 *
COUNT(c.IsConsecutive) /
NULLIF(COUNT(*), 0)
,2) AS FRACTION
FROM BY_PLAYERS AS c;
You could theoretically merge BY_PLAYERS into the outer query and use COUNT(DISTINCT but splitting them feels cleaner
I have the following problem.
Part of a task is to determine the visitor(s) with the most money spent between 2000 and 2020.
It just looks like this.
SELECT UserEMail FROM Visitor
JOIN Ticket ON Visitor.UserEMail = Ticket.VisitorUserEMail
where Ticket.Date> date('2000-01-01') AND Ticket.Date < date ('2020-12-31')
Group by Ticket.VisitorUserEMail
order by SUM(Price) DESC;
Is it possible to output more than one person if both have spent the same amount?
Use rank():
SELECT VisitorUserEMail
FROM (SELECT VisitorUserEMail, SUM(PRICE) as sum_price,
RANK() OVER (ORDER BY SUM(Price) DESC) as seqnum
FROM Ticket t
WHERE t.Date >= date('2000-01-01') AND Ticket.Date <= date('2021-01-01')
GROUP BY t.VisitorUserEMail
) t
WHERE seqnum = 1;
Note: You don't need the JOIN, assuming that ticket buyers are actually visitors. If that assumption is not true, then use the JOIN.
Use a CTE that returns all the total prices for each email and with NOT EXISTS select the rows with the top total price:
WITH cte AS (
SELECT VisitorUserEMail, SUM(Price) SumPrice
FROM Ticket
WHERE Date >= '2000-01-01' AND Date <= '2020-12-31'
GROUP BY VisitorUserEMail
)
SELECT c.VisitorUserEMail
FROM cte c
WHERE NOT EXISTS (
SELECT 1 FROM cte
WHERE SumPrice > c.SumPrice
)
or:
WITH cte AS (
SELECT VisitorUserEMail, SUM(Price) SumPrice
FROM Ticket
WHERE Date >= '2000-01-01' AND Date <= '2020-12-31'
GROUP BY VisitorUserEMail
)
SELECT VisitorUserEMail
FROM cte
WHERE SumPrice = (SELECT MAX(SumPrice) FROM cte)
Note that you don't need the function date() because the result of date('2000-01-01') is '2000-01-01'.
Also I think that the conditions in the WHERE clause should include the =, right?
when i'm doing it for one row its worked
update test set counte =
(select cOUNT(*)as counte from en_cours ,
test where DATEDIFF(DAY, en_cours.date, test.date)=0
and test.date='2019-11-13' group by test.date)
where test.date='2019-11-13'
but when i'm doing it for all rows
update test set counte =
(select COUNT(*) from en_cours ,
test where DATEDIFF(DAY, en_cours.date, test.date)=0
group by test.date)
where test.date= (select CONVERT(date , en_cours.date) from en_cours)
they said
"Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression."
any help please
Your error message is self explanatory. You can not set a condition like WHERE 10 = (A list of Integer like - 10,20,30). When you are using =, !=, <, <= , >, >= signs, the sub query must return a single value where as your query is returning more than 1 value and the error lies there. You can use CTE as below to achieve your requirement-
WITH CTE AS(
select test.date,COUNT(*) T
from en_cours
INNER JOIN test
ON en_cours.date = test.date
group by test.date
)
update A
SET A.counte = B.T
FROM Test A
INNER JOIN CTE B ON A.Date = B.Date
I want to count future Appointments made on the same day of an active appointment by Location. I expect multiple counts per Patient_ID given a date range. I am not sure if I need a temp table or if a subquery would work.
From the code below this is the error I get:
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
Definitions:
Appointment_DateTime - (Date) is the actual appointment event
DateTime_Scheduled - (Date) is the logging timestamp of future appointments
Description - (text) is the Location Description
Patient_ID - (int) is the unique patient ID
Appointment_ID - (int) is the unique Appointment ID
SQL
SELECT
loc.Description
,Count(app.Appointment_ID)
FROM [Ntier_HARH].[PM].[Appointments] app
join [Ntier_HARH].[PM].[Resources] res
on res.Resource_ID = app.Resource_ID
join [Ntier_HARH].[PM].[Practitioners] doc
on doc.Practitioner_ID = res.Practitioner_ID
join [Ntier_HARH].[PM].[Scheduling_Locations] loc
on loc.Scheduling_Location_ID = app.Scheduling_Location_ID
where
cast(app.DateTime_Scheduled as date) = '2017-01-16'
and app.status <> 'X'
and cast(app.Appointment_DateTime as date) =
(Select cast(DateTime_Scheduled as date)
from [Ntier_HARH].[PM].[Appointments]
where Patient_ID = app.Patient_ID)
group by loc.Description
You may use in instead of =
where
cast(app.DateTime_Scheduled as date) = '2017-01-16'
and app.status <> 'X'
and cast(app.Appointment_DateTime as date) IN (Select cast(DateTime_Scheduled as date) from [Ntier_HARH].[PM].[Appointments] where Patient_ID = app.Patient_ID)
group by loc.Description
Don't you also need to group by the PatientId? If you want the count of appointments by location only, then the subquery isn't necessary. I don't see why the other two tables are necessary either.
SELECT l.Description, Count(a.Appointment_ID)
FROM [Ntier_HARH].[PM].[Appointments] a
join [Ntier_HARH].[PM].[Scheduling_Locations] l
on l.Scheduling_Location_ID = a.Scheduling_Location_ID
where cast(a.DateTime_Scheduled as date) = '2017-01-16'
and a.status <> 'X'
group by l.Description
I need a little help to solve a query to count patients (ID) who have the average of the 3 last diastolic tension (TAD) < 90.
I've tried several type of nested subqueries with different errors.
This is my last version I've done:
SELECT CENTRO, COUNT ( DISTINCT ID )
FROM
(
SELECT PAC.CENTRO, PAC.ID, T.TAD
FROM IDDPAC PAC,
(
SELECT AVG(TA.TAD) TAD
FROM
(
SELECT
TEXT_TO_NUMBER ( PAG.TEXTO ) TAD
FROM IDDPAG PAG, DATE D
WHERE TRIM ( PAG.DGP )='AH'
AND PAG.ID=T.ID
AND PAG.FECHA=D.OMI
AND D.TIME_DATE::DATE BETWEEN DATE '2012-01-01'
AND DATE '2012-12-31'
ORDER BY PAG.FECHA DESC LIMIT 3
) TA
) T
WHERE PAC.CENTRO='10040110' AND T.ID = PAC.ID
GROUP BY PAC.CENTRO , PAC.ID
)
A
WHERE T.TAD < 90
GROUP BY CENTRO
And I get the following error:
ERROR: falta una entrada para la tabla «t» en la cláusula FROM
LINE 31: AND PAG.ID=T.ID
^
********** Error **********
Translation:
ERROR: missing an entry for the table «t» in the clause FROM
LINE 31: AND PAG.ID=T.ID
^
********** Error **********
To get the average of the last three values, use row_number() to enumerate the values. Then choose the last three and take the average. This gives you the patient level information:
SELECT PAC.CENTRO, PAG.ID, AVG(TA.TAD) AS TAD
FROM (SELECT PAG.ID, TEXT_TO_NUMBER ( PAG.TEXTO ) as TAD,
ROW_NUMBER() OVER (PARTITION BY PAG.ID ORDER BY D.TIME_DATE DESC) as seqnum
FROM IDDPAG PAG JOIN
DATE D
ON PAG.FECHA = D.OMI JOIN
IDDPAC PAC
ON PAC.ID = PAG.ID
WHERE TRIM ( PAG.DGP )='AH' AND
D.TIME_DATE::DATE BETWEEN DATE '2012-01-01' AND DATE '2012-12-31'
) TA
WHERE SEQNUM <= 3
GROUP BY PAC.CENTRO, PAD.ID
HAVING AVG(TA.TAD) < 90;
The count by centro would just be:
SELECT CENTRO, COUNT(*)
FROM (SELECT PAC.CENTRO, PAG.ID, AVG(TA.TAD) AS TAD
FROM (SELECT PAG.ID, TEXT_TO_NUMBER ( PAG.TEXTO ) as TAD,
ROW_NUMBER() OVER (PARTITION BY PAG.ID ORDER BY D.TIME_DATE DESC) as seqnum
FROM IDDPAG PAG JOIN
DATE D
ON PAG.FECHA = D.OMI JOIN
IDDPAC PAC
ON PAC.ID = PAG.ID
WHERE TRIM ( PAG.DGP )='AH' AND
D.TIME_DATE::DATE BETWEEN DATE '2012-01-01' AND DATE '2012-12-31'
) TA
WHERE SEQNUM <= 3
GROUP BY PAC.CENTRO, PAD.ID
HAVING AVG(TA.TAD) < 90
) TA
GROUP BY CENTRO;
The problem is, exactly as the error indicates, that 'T' is not defined in the place it is requested. Your error is in the innermost subquery:
SELECT
TEXT_TO_NUMBER ( PAG.TEXTO ) TAD
FROM IDDPAG PAG, DATE D
WHERE TRIM ( PAG.DGP )='AH'
AND PAG.ID=T.ID
AND PAG.FECHA=D.OMI
AND D.TIME_DATE::DATE BETWEEN DATE '2012-01-01'
AND DATE '2012-12-31'
ORDER BY PAG.FECHA DESC LIMIT 3
But there is no T defined here to be used in the PAG.ID=T.ID portion of your WHERE clause. Did you mean to join on a table called T? Or did you mean to use D.ID instead?