how to delete from table based on query results - sql

I have the following query which spits out some values and I need to basically modify it so that I can delete some rows from the source table based on whether the Ticker symbol and date are represented in the output of the select query.
Here is the query.
;with cte_tenPct as (
select exchange, ticker
, CurrentDate = date, Prior_Date = (lag(date) over(partition by ticker order by date))
, Current_open = [open] , Prior_open = (lag([open]) over(partition by ticker order by date))
, Current_high = [high] , Prior_high = (lag([high]) over(partition by ticker order by date))
, Current_low = [low] , Prior_low = (lag([low]) over(partition by ticker order by date))
, Current_close = [close] , Prior_close = (lag([close]) over(partition by ticker order by date))
from dbo.V with (nolock)
)
select * from cte_tenPct
where (Current_open <> 0 and Current_open = Prior_open / 10)
and (Current_high <> 0 and Current_high = Prior_high / 10)
and (Current_low <> 0 and Current_low = Prior_low / 10)
and (Current_close <> 0 and Current_close = Prior_close / 10)
Here are the results (just the relevant parts)
So, I want to basically start the query with: DELETE FROM V where V.Ticker = cte_tenPct.Ticker and V.Date = cte_tenPct.CurrentDate IN --then I would have the select query below. Can someone help me out with the syntax. Thanks

;with cte_tenPct as (
select exchange, ticker
, CurrentDate = date, Prior_Date = (lag(date) over(partition by ticker order by date))
, Current_open = [open] , Prior_open = (lag([open]) over(partition by ticker order by date))
, Current_high = [high] , Prior_high = (lag([high]) over(partition by ticker order by date))
, Current_low = [low] , Prior_low = (lag([low]) over(partition by ticker order by date))
, Current_close = [close] , Prior_close = (lag([close]) over(partition by ticker order by date))
from dbo.V with (nolock)
)
delete from cte_tenPct
where (Current_open <> 0 and Current_open = Prior_open / 10)
and (Current_high <> 0 and Current_high = Prior_high / 10)
and (Current_low <> 0 and Current_low = Prior_low / 10)
and (Current_close <> 0 and Current_close = Prior_close / 10)
Basically you just need to delete instead of selecting the cte resutls.
And of cource you can either delete all entries that exist in the cte results or use a where clause to filter which entries will be deleted.

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

The query I ran returns 2 of the same column which isn't allowed in tableau and I can't fix the query

I need to be able to get rid of one of the workdate and one of the sr_name columns but I can't figure out how to.
I'm getting the query returned like this:
Query
I'm also getting this error message when entered into tableau:
The column 'sr_name' was specified multiple times for 'Custom SQL Query'.
Below is the code I have. If I remove a sr_name from either subquery there will be an error in the join clause.
select *
from
(
select s.sr_name, cast(punchdatetime as date) as workdate,
((datediff(second, min(case when p.InOut = 1 then punchdatetime end),
max(case when p.InOut = 0 then punchdatetime end))/3600) - .5) as
hoursworked
from PunchClock p join ServiceReps s on p.ServRepID = s.ServRepID
where punchyear >= 2019
group by s.sr_name, cast(punchdatetime as date)
) v
join
(
select sr_name, t.*,
calls = (select count(*) from CRM_Correspondence cr where
cast(cr.DateCreated as date) = workdate and StatusType like '%call%' and
cr.ServRepID = t.servrepid),
reaches = (select count(*) from CRM_Correspondence cr where
cast(cr.DateCreated as date) = workdate and (StatusType = 'call reached'
or StatusType like '%SCHEDULE%') and cr.ServRepID = t.servrepid),
books = (select count(*) from os_appointments o where cast(o.DateCreated
as date) = workdate and isnull(o.confirmedby, o.booked_by) =
t.servrepid),
attends = (select count(*) from os_appointments o where
cast(o.DateCreated as date) = workdate and isnull(o.confirmedby,
o.booked_by) = t.servrepid and o.appointmentStatus = 'attended')
from
(
select cast(cor.datecreated as date) workdate, cor.ServRepID
from CRM_Correspondence cor
where cor.datecreated > '2019-01-01'
group by cast(cor.datecreated as date), cor.servrepid
) t
join ServiceReps sr on t.ServRepID = sr.ServRepID
) u on v.sr_name = u.sr_name and v.workdate = u.workdate
I need the same results just without the duplicate column so I can enter the query into tableau.
This is challenging because you have so many subqueries here. This could be refactored to use a single query which is what I would do. But using the existing query you could do something along these lines.
I had to format this very differently so I could isolate each piece.
select v.sr_name
, v.workdate
, v.hoursworked
, u.ServRepID
, u.calls
, u.reaches
, u.books
, u.attends
from
(
select s.sr_name
, cast(punchdatetime as date) as workdate
, ((datediff(second, min(case when p.InOut = 1 then punchdatetime end), max(case when p.InOut = 0 then punchdatetime end))/3600) - .5) as hoursworked
from PunchClock p
join ServiceReps s on p.ServRepID = s.ServRepID
where punchyear >= 2019
group by s.sr_name
, cast(punchdatetime as date)
) v
join
(
select sr_name
, t.*
, calls =
(
select count(*)
from CRM_Correspondence cr
where cast(cr.DateCreated as date) = workdate
and StatusType like '%call%'
and cr.ServRepID = t.servrepid
)
, reaches =
(
select count(*)
from CRM_Correspondence cr
where cast(cr.DateCreated as date) = workdate
and (StatusType = 'call reached' or StatusType like '%SCHEDULE%')
and cr.ServRepID = t.servrepid
)
, books =
(
select count(*)
from os_appointments o
where cast(o.DateCreated as date) = workdate and isnull(o.confirmedby, o.booked_by) = t.servrepid
)
, attends =
(
select count(*)
from os_appointments o
where cast(o.DateCreated as date) = workdate
and isnull(o.confirmedby, o.booked_by) = t.servrepid
and o.appointmentStatus = 'attended'
)
from
(
select cast(cor.datecreated as date) workdate
, cor.ServRepID
from CRM_Correspondence cor
where cor.datecreated > '2019-01-01'
group by cast(cor.datecreated as date)
, cor.servrepid
) t
join ServiceReps sr on t.ServRepID = sr.ServRepID
) u on v.sr_name = u.sr_name
and v.workdate = u.workdate

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

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')

no column was specified for column [x] of [table] and invalid column name

When running the following query, I get the desired results, but SSMS indicates that "no column was specified for column 2 of 'MonthlyTotals' when I mouse over the table alias and when I mouse over the "Totals" in the AVG function, it specifies that it's an invalid column name.
SELECT AVG(Totals) as 'MonthlyAvg' from
(
SELECT [DATE], SUM(Assets) as 'Totals'
FROM Assets inner join Funds on Assets.FundCode = Funds.FundCode
WHERE FeeGroupID = 17
and (([Date] >= '1/1/2013')
AND ([Date] <= '4/1/2013'))
and ((Funds.EndDt >= '4/1/2013') OR (Funds.EndDt is null))
GROUP BY [DATE]
) as MonthlyTotals
Total guess, but try this alternate syntax.
SELECT [MonthlyAvg] = AVG(Totals) from
(
SELECT [DateOf] = [DATE] , [Totals] = SUM(Assets)
FROM Assets inner join Funds on Assets.FundCode = Funds.FundCode
WHERE FeeGroupID = 17
and (([Date] >= '1/1/2013')
AND ([Date] <= '4/1/2013'))
and ((Funds.EndDt >= '4/1/2013') OR (Funds.EndDt is null))
GROUP BY [DATE]
) as MonthlyTotals

SQL GROUP BY AND VALUE AND NON UNIQUE VALUES

This is my SQL:
SELECT *
FROM (
SELECT DISTINCT real_dep_date,
real_price,
resort_name,
season_id,
min_occ,
free_sell,
MIN(real_price) OVER (PARTITION BY resort_name,real_dep_date) AS min_price
FROM deals_panel_view
WHERE ([1pax_disc] = [1pax_disc])
AND (real_dep_date >= season_start)
AND (season_name = 'winter 2012')
AND (chalet_url <> '')
AND (real_price <> 0)
AND (real_dep_date <= season_end)
AND (combined_chalet = 0)
AND (availability_spaces <> 0)
) deals_panel_view
WHERE min_price = real_price
This works but what happens is I get 3 results for a certain resort. This is because there are 3 chalets that are exactly the same.
I want to only show one, so I guess I would use a limit, but I don't know where.
I am using SQL Server 2005.
Any help would be great.
Try with this...
Select real_dep_date,
real_price,
resort_name,
season_id,
min_occ,
free_sell,
min_price FROM (SELECT ROW_NUMBER() over (PARTITION BY resort_name,real_dep_date ORDER BY resort_name) as ROW,*
FROM (
SELECT DISTINCT real_dep_date,
real_price,
resort_name,
season_id,
min_occ,
free_sell,
MIN(real_price) OVER (PARTITION BY resort_name,real_dep_date) AS min_price
FROM deals_panel_view
WHERE ([1pax_disc] = [1pax_disc])
AND (real_dep_date >= season_start)
AND (season_name = 'winter 2012')
AND (chalet_url <> '')
AND (real_price <> 0)
AND (real_dep_date <= season_end)
AND (combined_chalet = 0)
AND (availability_spaces <> 0)
) deals_panel_view
WHERE min_price = real_price
) Temp
where Row = 1