How do I resolve an "incorrect syntax near ','"? - sql

Im writing a query for a campaign and whenever i try to run it I get an error saying the syntax isn't correct.
select
opp.*
from
(
select
opp.*,
row_number() over (partition by opp.contact_email_address order by opp.status_date desc) as row_number
from
opportunity_data opp
where
opp.email_bounced = 'false'
and opp.email_unsubscribe = 'false'
and opp.first_mkt_medium not in ('partner', 'inbound_outbound')
and opp.latest_mkt_medium not in ('partner', 'inbound_outbound')
and datediff (day, cast(latest_rfq_submitted_date as date), cast(getdate() as date)) > 30
and opp.on_cover = 'no'
and opp.primary_group in ('Market_trader', 'Food_stand', 'Mobile_food_van', 'Caterer')
and opp.site = 'simplybusiness'
and opp.opportunity_status = ('quote_recieved', 'rfq_submitted', 'policy_expired_not_renewed')
) opp
where row_number = 1

Check with this:
select
opp.*
from
(
select
opp.*,
row_number() over (partition by opp.contact_email_address order by opp.status_date desc) as row_number
from
opportunity_data opp
where
opp.email_bounced = 'false'
and opp.email_unsubscribe = 'false'
and opp.first_mkt_medium not in ('partner', 'inbound_outbound')
and opp.latest_mkt_medium not in ('partner', 'inbound_outbound')
and datediff (day, cast(latest_rfq_submitted_date as date), cast(getdate() as date)) > 30
and opp.on_cover = 'no'
and opp.primary_group in ('Market_trader', 'Food_stand', 'Mobile_food_van', 'Caterer')
and opp.site = 'simplybusiness'
and opp.opportunity_status in ('quote_recieved', 'rfq_submitted', 'policy_expired_not_renewed')
) opp
where row_number = 1

The error appears because of your last where line. You cant use it like this. I think you wanted to use in instead of =:
AND opp.opportunity_status IN ('quote_recieved', 'rfq_submitted', 'policy_expired_not_renewed')

Related

SQL - Adding conditions to SELECT

I have a table which has a timestamp and inCycle status of a machine. I'm using two CTE's and doing an INNER JOIN on row number so I can easily compare the timestamp of one row to the next. I have the DATEDIFF working and now I need to look at the inCycle status. Basically, if the inCycleThis and inCycleNext both = 1, I need to add it to an InCycle total.
Similarly (Shown table will make this clear):
incycleThis/next = 0,1 = not in cycle
incycleThis/next = 0,0 = not in cycle
incycleThis/next = 1,1 = in cycle
If I was doing this client side, this would be pretty simple. I need to do this in a stored procedure though due to there being a lot of records. I'd love to use an 'IF' in the SELECT section, but it seems that's not how it works.
The result I'm looking for at the end is simply: InCycle = Xtime. Something like:
SUM(Diff_seconds if((InCycleThis = 1 AND InCycleNext = 1) OR (InCycleThis = 1 AND InCycleNext = 0))
This is what I have so far:
WITH History_CTE (DT, MID, FRO, IC, RowNum)
AS
(
SELECT DateAndTime
,MachineID
,FeedRateOverride
,InCycle
,ROW_NUMBER()OVER(ORDER BY MachineID, DateAndTime) AS "row number"
FROM History
WHERE DateAndTime >= '2020-11-15'
AND DateAndTime < '2020-11-16'
),
History2_CTE (DT2, MID2, FRO2, IC2, RowNum2)
AS
(
SELECT DateAndTime
,MachineID
,FeedRateOverride
,InCycle
,ROW_NUMBER()OVER(ORDER BY MachineID, DateAndTime) AS "row number"
FROM History
WHERE DateAndTime >= '2020-11-15'
AND DateAndTime < '2020-11-16'
)
SELECT DT as 'TimeStamp'
,DT2 as 'TimeStamp Next Row'
,MID
,FRO
,IC as 'InCycle this'
,IC2 as 'InCycle next'
,RowNum
,DATEDIFF(s, History2_CTE.DT2, History_CTE.DT) AS 'Diff_seconds'
FROM History_CTE
INNER JOIN
History2_CTE ON History_CTE.RowNum = History2_CTE.RowNum2 + 1
Consider adding a third CTE to first conditionally calculate your needed value. Then aggregate for final statement. Recall CTEs can reference previously defined CTEs. Be sure to always quailfy columns with table aliases in JOIN queries.
WITH
... first two ctes...
, sub AS (
SELECT h1.DT AS 'TimeStamp'
, h2.DT2 AS 'TimeStamp Next Row'
, h1.MID
, h1.FRO
, h1.IC AS 'InCycle this'
, h2.IC2 AS 'InCycle next'
, h1.RowNum
, DATEDIFF(s, h2.DT2, h1.DT) AS 'Diff_seconds'
, CASE
WHEN (h1.IC = 1 AND h2.IC2 = 1) OR (h1.IC= 1 AND h2.IC2 = 0)
THEN DATEDIFF(s, h2.DT2, h1.DT)
END AS 'IC_Diff_seconds'
FROM History_CTE h1
INNER JOIN History2_CTE h2
ON h1.RowNum = h2.RowNum2 + 1
)
SELECT SUM([Diff_seconds]) AS Diff_seconds_Total
, SUM([IC_Diff_seconds]) AS IC_Diff_seconds_Total
FROM sub
And if needing to add groupings, incorporate GROUP BY:
SELECT h1.MID
, h1.FRO
, SUM([Diff_seconds]) AS Diff_seconds_Total
, SUM([IC_Diff_seconds]) AS IC_Diff_seconds_Total
FROM sub
GROUP BY h1.MID
, h1.FRO
Even aggregate calculations by day:
SELECT CONVERT(date, [TimeStamp]) AS [Day]
, SUM([Diff_seconds]) AS Diff_seconds_Total
, SUM([IC_Diff_seconds]) AS IC_Diff_seconds_Total
FROM sub
GROUP BY CONVERT(date, [TimeStamp])
The result I'm looking for at the end is simply: InCycle = Xtime. Something like:
SUM(Diff_seconds if((InCycleThis = 1 AND InCycleNext = 1) OR (InCycleThis = 1 AND InCycleNext = 0))
As I understand your question, you just need to sum the difference betwen the timestamp of "in cycle" rows and the timestamp of the next row.
select machineid,
sum(datediff(s, dateandtime, lead_dateandtime)) as total_in_time
from (
select h.*,
lead(dateandtime) over(partition by machineid order by dateandtime) as lead_dateandtime
from history h
) h
where inclycle = 1
group by machineid

Select a line equal to 'X' without TOP 'N' plus the previous line 'Y' in SQL Server?

I need to return in a query only the last lines with 'ProductStatus' equal 'Stop' and the previous line.
I have the table:
And need to get this result:
How do I do this in SQL Server?
One method uses window functions to calculate the last stop and then get the row before that:
select t.*
from (select t.*,
lead(seqnum_ps) over (partition by producttype order by datevalue) as next_seqnum_ps,
lead(status) over (partition by producttype order by datevalue) as next_status
from (select t.*,
row_number() over (partition by producttype, product_status order by datevalue desc) as seqnum_ps
from t
) t
) t
where (seqnum_ps = 1 and product_status = 'Stop') or
(next_seqnum_ps = 1 and next_product_status = 'Stop');
An alternative method gets the maximum stop time and uses that:
select t.*
from (select t.*,
max(case when product_status = 'Stop' then datevalue end) over (partition by producttype) as max_stop_dv,
lead(datevalue) over (partition by producttype order by datevalue) as next_dv
from t
) t
where datevalue = max_stop_dv or
next_dv = max_stop_dv;

Case statement based in max min dates

I have a columns as Memnumber, activity type, activity date, activity ID. One member can have activities after few days. I want to write a case statement that if the activity date is most initial then INITIAL and if activity is most recent then MR and if there is any activity in between these 2 dates then BETWEEN. They need to be grouped by Memnumber and treatment type.
I wrote query as :
--MR County Tree
SELECT T0.MEMBERNUMBER,
T0.ACTIVITYTYPE,
T1.MR_CY17,
T1.IN_CY17,
T0.ACTIVITY_DATE,
(T0.ACTIVITYID)
FROM DLA_EXTRACT_FINAL T0
INNER JOIN (
SELECT MEMBERNUMBER,
ACTIVITYTYPE,
MAX(ACTIVITY_DATE) MR_CY17,
MIN(ACTIVITY_DATE) IN_CY17
FROM DLA20_EXTRACT_FINAL
WHERE to_char(ACTIVITY_DATE, 'YYYYMMDD') >= 20170101
AND to_char(ACTIVITY_DATE, 'YYYYMMDD') <= 20171231
GROUP BY MEMBERNUMBER,
ACTIVITYTYPE
) T1 ON T0.MEMBERNUMBER = T1.MEMBERNUMBER
AND T0.ACTIVITYTYPE = T1.ACTIVITYTYPE
AND T0.ACTIVITY_DATE = T1.MR_CY17
--where T0.ACTIVITYTYPE='MT'
WHERE t0.MEMBERNUMBER = 'M500085268'
GROUP BY T0.MEMBERNUMBER,
T0.ACTIVITYTYPE,
T1.MR_CY17,
T1.IN_CY17,
T0.ACTIVITYID,
T0.ACTIVITY_DATE
ORDER BY T0.MEMBERNUMBER,
T0.ACTIVITYTYPE,
T1.MR_CY17,
T1.IN_CY17.
Looking for a solution.
You want to use window functions. Something like:
SELECT T0.MEMBERNUMBER,
T0.ACTIVITYTYPE,
T0.ACTIVITY_DATE,
T0.ACTIVITYID,
case when row_number() over (partition by T0.MEMBERNUMBER, T0.ACTIVITYTYPE
order by T0.ACTIVITY_DATE) = 1 then 1 else 0 end most_initial,
case when row_number() over (partition by T0.MEMBERNUMBER, T0.ACTIVITYTYPE
order by T0.ACTIVITY_DATE desc) = 1 then 1 else 0 end most_recent
FROM DLA_EXTRACT_FINAL T0
Then you can use case statements to label as INITIAL if most_intial = 1, MR if most_recent = 1, or BETWEEN if both are 0.

CASE Statement inside a subquery

I was able to create the following query after help from the post below
select * from duppri t
where exists (
select 1
from duppri
where symbolUP = t.symbolUP
AND date = t.date
and price <> t.price)
ORDER BY date
SQL to check when pairs don't match
I have now realized that I need to add a case statement to indicate when all the above criteria fits, but the type value is equal between duppri and t.duppri. This occurs because of case sensitivity. This query is an attempt to clean up a portfolio accounting system that unfortunately allowed numerous duplicates because it didn't have strong referential integrity or constraints.
I would like the case statement to produce the column 'isMatch'
Date |Type|Symbol |SymbolUP |Concatt |Price |IsMatch
6/30/1995 |gaus|313586U72|313586U72|gaus313586U72|109.25|Different
6/30/1995 |gbus|313586U72|313586U72|gbus313586U72|108.94|Different
6/30/1995 |agus|SRR |SRR |agusSRR |10.25 |Different
6/30/1995 |lcus|SRR |SRR |lcusSRR |0.45 |Different
11/27/1996|lcus|LLY |LLY |lcusLLY |76.37 |Matched
11/27/1996|lcus|lly |LLY |lcusLLY |76 |Matched
11/28/1996|lcus|LLY |LLY |lcusLLY |76.37 |Matched
11/28/1996|lcus|lly |LLY |lcusLLY |76 |Matched
I tried the following CASE statement but it is creating errors
SELECT * from duppri t
where exists (
select 1,
CASE IsMatch WHEN [type] = [t.TYPE] THEN 'Matched' ELSE 'Different' END
from duppri
where symbolUP = t.symbolUP
AND date = t.date
and price <> t.price)
ORDER BY date
You could just use window functions, if I understand correctly:
select d.*,
(case when mint = maxt
then 'Matched' else 'Different'
end)
from (select d.*,
min(type) over (partition by symbolup, date) as mint,
max(type) over (partition by symbolup, date) as maxt,
min(price) over (partition by symbolup, date) as minp,
max(price) over (partition by symbolup, date) as maxp
from duppri d
) d
where minp <> maxp
order by date;
The subquery used with the exists predicate can't and won't return anything other than true/false but you can accomplish what you want using a subquery like this, which should work:
select
*,
(select
CASE when count(distinct type) = 1 THEN 'Matched' ELSE 'Different' END
from duppri
where symbol = t.symbol and date = t.date
) IsMatch
from duppri t
where exists (
select 1
from duppri
where symbol = t.symbol
and price <> t.price);

SQL subquery question

I have the following SQL
SELECT
Seq.UserSessionSequenceID,
Usr.SessionGuid,
Usr.UserSessionID,
Usr.SiteID,
Seq.Timestamp,
Seq.UrlTitle,
Seq.Url
FROM
tblUserSession Usr
INNER JOIN
tblUserSessionSequence Seq ON Usr.UserSessionID = Seq.UserSessionID
WHERE
(Usr.Timestamp > DATEADD(mi, -45, GETDATE())) AND (Usr.SiteID = 15)
ORDER BY Usr.Timestamp DESC
Pretty simple stuff. There are by nature multiple UserSessionIDs rows in tblUserSessionSequence. I ONLY want to return the latest (top 1) row with unique UserSessionID. How do I do that?
You can use the windowing function ROW_NUMBER to number the rows for each user and select only those rows that have row number 1.
SELECT
UserSessionSequenceID,
SessionGuid,
UserSessionID,
SiteID,
Timestamp,
UrlTitle,
Url
FROM (
SELECT
Seq.UserSessionSequenceID,
Usr.SessionGuid,
Usr.UserSessionID,
Usr.SiteID,
Usr.Timestamp AS UsrTimestamp,
Seq.Timestamp,
Seq.UrlTitle,
Seq.Url,
ROW_NUMBER() OVER (PARTITION BY Usr.UserSessionID
ORDER BY Seq.UserSessionSequenceID DESC) AS rn
FROM
tblUserSession Usr
INNER JOIN
tblUserSessionSequence Seq ON Usr.UserSessionID = Seq.UserSessionID
WHERE
(Usr.Timestamp > DATEADD(mi, -45, GETDATE())) AND (Usr.SiteID = 15)
) T1
WHERE rn = 1
ORDER BY UsrTimestamp DESC
If you're looking to return only a single row in your query (i.e., the ID with the latest timestamp), just change
SELECT
to
SELECT TOP 1
If you're looking to obtain a single row for each UserSessionID, but you want to ensure that you get the one with the latest TimeStamp, that's slightly more complex.
You could do something like this:
SELECT
Seq.UserSessionSequenceID,
Usr.SessionGuid,
Usr.UserSessionID,
Usr.SiteID,
Seq.Timestamp,
Seq.UrlTitle,
Seq.Url
FROM
tblUserSession Usr
INNER JOIN
(SELECT
UserSessionSequenceID,
UserSessionID,
Timestamp,
UrlTitle,
Url,
ROW_NUMBER() over (PARTITION BY UserSessionID ORDER BY UserSessionSequenceID) AS nbr
FROM tblUserSessionSequence) Seq ON Usr.UserSessionID = Seq.UserSessionID AND Seq.nbr = 0
WHERE
(Usr.Timestamp > DATEADD(mi, -45, GETDATE())) AND (Usr.SiteID = 15)
ORDER BY Usr.Timestamp DESC