Help with a SQL Query - sql

I am wanting to perform a Threshold query, whereby one would take the Value of a field from Today, and compare it to the value from yesterday, this query would look something like this, but obviously, it is wrong, and I can't find how to do it:
select
TableB.Name,
TableA.Charge,
(
select Charge
from TableA
where (DateAdded >= '13/10/2009' and DateAdded < '14/10/2009')
)
from TableA
inner join
TableB on TableB.ID = TableA.ID
where
TableA.DateAdded >= '10/14/2009'
order by
Name asc
Just a quick note, I am looking for two CHARGE fields, not the dates. The date manipulation is simply for Today and Yesterday, nothing more.
At the end of this, I want to do a calculation on the two returned charge fields, so if its easier to show that, that would also be great.
Thanks in advance
Kyle
EDIT1:
The data I am looking for is like so:
Yesterday, we input a charge of 500 to MachineA
Today we input a charge of 300 to MachineA
We run the query, and results I need are as follows:
Name = MachineA
Charge = 300
YesterdayCharge = 500

If you really need previous date (including weekends etc), then following query should do the job. Otherwise please post data samples and expected results:
SELECT TableB.Name,
TableA.Charge,
prev.Charge AS PrevCharge
FROM TableA
INNER JOIN TableB
ON TableA.ID = TableB.ID
LEFT JOIN TableA prev
ON TableA.ID = prev.ID
--// use this if DateAdded contains only date
--AND TableA.DateAdded = DATEADD(day, +1, prev.dateAdded)
--// use this if DateAdded contains also time component
AND CONVERT(DATETIME, CONVERT(CHAR(8), TableA.DateAdded, 112), 112) = DATEADD(day, +1, CONVERT(DATETIME, CONVERT(CHAR(8), prev.dateAdded, 112), 112))
edit-1: added option in JOIN for cases when DateAdded contains time as well

something like this?
SELECT
B.Name,
A.Charge,
DATEPART(day, A.DateAdded) as day
FROM
TableA A, Table B
WHERE
B.ID = A.ID AND
A.DateAdded BETWEEN DATEADD(day, -1, GETDATE()) AND GETDATE()
GROUP BY
B.Name,
A.Charge,
A.DateAdded

Try this:
DECLARE #ValuesTable TABLE(Name VARCHAR(20), Charge INT, DateAdded DATETIME)
INSERT INTO #ValuesTable
SELECT 'Name1', 10, DATEADD(dd, 2, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name2', 20, DATEADD(dd, 2, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name1', 30, DATEADD(dd, 1, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name2', 40, DATEADD(dd, 1, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name1', 50, DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name2', 60, DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name1', 70, DATEADD(dd, -1, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name3', 80, DATEADD(dd, -1, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name1', 90, DATEADD(dd, -2, DATEDIFF(dd, 0, GETDATE())) UNION
SELECT 'Name2', 100, DATEADD(dd, -2, DATEDIFF(dd, 0, GETDATE()))
SELECT
ISNULL(T.Name,Y.Name) AS Name,
SUM(ISNULL(Y.Charge,0)) AS Yesterday, SUM(ISNULL(T.Charge,0)) AS Today,
SUM(ISNULL(T.Charge,0)) - SUM(ISNULL(Y.Charge,0)) AS Diff
FROM(
SELECT Name, Charge
FROM #ValuesTable
WHERE DateAdded BETWEEN DATEADD(day, -2, GETDATE())
AND DATEADD(day, -1, GETDATE())
) AS Y
FULL JOIN(
SELECT Name, Charge
FROM #ValuesTable
WHERE DateAdded BETWEEN DATEADD(day, -1, GETDATE()) AND GETDATE()
) AS T ON ISNULL(T.Name,Y.Name) = ISNULL(Y.Name,T.Name)
GROUP BY ISNULL(T.Name,Y.Name) , ISNULL(Y.Name,T.Name)

It may be just a typo in SO but if you are using date strings '14/10/2009' and '10/14/2009' in the same query it will never work.
No matter which date format you are using one of them has too many months in it.

Related

Incorrect syntax near my alias when joining sub-queries?

My code is provided below. I get the error
"Incorrect syntax near the keyword 'otb'" (line 48)
and
"Incorrect syntax near the keyword 'otb_ly' "
I have no idea what this could mean! Because it makes sense to me to join my two sub-queries (that I've named otb and otb_ly).
On their own the sub-queries work just fine.
declare #snapLY table (hotel_id tinyint, import_date date)
insert into #snapLY select hotel_id, max(import_date) from [UKRMC].[dbo].[block_res]
where import_date <= convert(date, DATEADD(day, 1, DATEADD(year, -1, GETDATE()) ) )
group by hotel_id
select otb.sita,
otb.month_TY,
otb.year_TY,
otb.Market_segment,
otb.rn_TY as OTB_rn_TY,
otb.rev_TY as OTB_rev_TY
--otb_ly.rev_LY as OTB_rev_LY,
--otb_ly.rn_LY as OTB_rn_LY
(
select contacts.sita,
data.hotel_id,
data.month_TY
,data.year_TY
,Market_segment = seg.SEG
,rn_TY = ISNULL(datatwo.rn_TY,0)
,rev_TY = ISNULL(datatwo.rev_TY, 0)
from (
SELECT hotel_id, datename(month, DATEARRIVED) as month_TY, datename(year, DATEARRIVED) year_TY
FROM [UKRMC].[dbo].[revenue] rev
JOIN [UKRMC].[dbo].[contacts] contacts on rev.hotel_id = contacts.ID
WHERE DATEARRIVED BETWEEN DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '19000101') -- first day of the month
AND DATEADD(MONTH, 5, DATEADD(DAY,-DAY(DATEADD(MONTH, 1, GETDATE())), DATEADD(MONTH, 1, GETDATE()))) -- 6 months later
and sita not like '%GLARR%'
group by hotel_id, datename(month, DATEARRIVED), datename(year, DATEARRIVED)
) data
cross join (
select SEG
from [UKRMC].[dbo].[Segmentation]
where SEG in ('RAC', 'BIT', 'BIQ', 'CBI', 'TOF', 'QOF', 'BAO', 'FIT', 'LYO', 'RER', 'OTH', 'NRG', 'XXX', 'CRW', 'BGR', 'BGO', 'LGR', 'LGS')
) seg
left join (
SELECT hotel_id, market_segment, datename(month, DATEARRIVED) month_TY, datename(year, DATEARRIVED) year_TY, sum(AMTROOM) as rev_TY, sum(STAYDAYS) as rn_TY
FROM [UKRMC].[dbo].[revenue] revtwo
WHERE DATEARRIVED BETWEEN DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '19000101') -- first day of the month
AND DATEADD(MONTH, 5, DATEADD(DAY,-DAY(DATEADD(MONTH, 1, GETDATE())), DATEADD(MONTH, 1, GETDATE()))) -- 6 months later
AND hotel_id != 61 --not GLARR, id taken from contacts table
GROUP BY hotel_id, datename(month, DATEARRIVED), datename(year, DATEARRIVED), market_segment
) datatwo on data.hotel_id = datatwo.hotel_id and seg.SEG = datatwo.market_segment and data.month_TY = datatwo.month_TY and data.year_TY = datatwo.year_TY
join [UKRMC].[dbo].[contacts] contacts on contacts.id = data.hotel_id
) otb
LEFT JOIN
(
SELECT sita, market_seg, month_LY, year_LY, sum(rev_LY) as rev_LY, sum(rn_LY) as rn_LY
FROM (
SELECT block.hotel_id, SITA
,datename(month,stay_date) as month_LY
,datename(year, stay_date) as year_LY
,sum(rev_room) as rev_LY
,sum(quantity) as rn_LY
,market_seg
FROM [UKRMC].[dbo].[block_res] block
JOIN #snapLY spit on block.hotel_id = spit.hotel_id and block.import_date = spit.import_date
JOIN [UKRMC].[dbo].[Contacts] contacts on block.hotel_id = contacts.ID
WHERE stay_date >= DATEADD(year, -1, DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '19000101'))
--stay_date >= DATEADD(year, -1, getdate())
and stay_date <= DATEADD(year, -1, DATEADD(MONTH, 5, DATEADD(DAY,-DAY(DATEADD(MONTH, 1, GETDATE())), DATEADD(MONTH, 1, GETDATE()))))
group by sita, market_seg, block.hotel_id, datename(month,stay_date),datename(year, stay_date)
UNION ALL
SELECT revenue.HOTEL_ID, SITA
,datename(month,DATEARRIVED) as month_LY
,datename(year,DATEARRIVED) as year_LY
,sum(AMTROOM) as rev_LY
,sum(STAYDAYS) as rn_LY
,market_segment
FROM [UKRMC].[dbo].[revenue] revenue
JOIN [UKRMC].[dbo].[Contacts] contacts on revenue.HOTEL_ID = contacts.ID
JOIN #snapLY spit on revenue.HOTEL_ID = spit.hotel_id
WHERE DATEARRIVED between DATEADD(year, -1, DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '19000101'))
and DATEADD(day, -1, DATEADD(year, -1, getdate()))
and DATEARRIVED < spit.import_date
GROUP BY sita, revenue.HOTEL_ID, datename(month,DATEARRIVED), datename(year,DATEARRIVED), market_segment
) union_LY
GROUP BY sita, market_seg, hotel_id, month_LY, year_LY
) otb_ly
on otb.sita = otb_ly.sita and otb.Market_segment = otb_ly.market_seg and otb.month_LY = otb_ly.month_LY and otb.year_LY = otb_ly.year_LY
You're missing a FROM on Line 14:
...
--otb_ly.rn_LY as OTB_rn_LY
FROM
(
...
That query, in all honestly, needs a massive rework... That is really difficult to read.

SQL change day in my language in select statement

How can I change the day in my language with a select statement like use if:
if day= sunday then set day = minggu
You need some kind of conversion. Take a look at example below:
WITH Src AS
(
SELECT * FROM (VALUES
(GETDATE()),
(DATEADD(DAY, 1, GETDATE())),
(DATEADD(DAY, 2, GETDATE())),
(DATEADD(DAY, 3, GETDATE())),
(DATEADD(DAY, 4, GETDATE())),
(DATEADD(DAY, 5, GETDATE())),
(DATEADD(DAY, 6, GETDATE()))
) T(Dates)
)
SELECT
FORMAT(Dates, 'ddd', 'id-ID') LocalizedFormat,
SUBSTRING('MingguSen Sel Rabu Kamis Jumat Sabtu ', 6*(DATEPART(WEEKDAY,Dates)-1)+1, 6) LocalizedExpression
FROM Src
It results in:
LocalizedFormat LocalizedExpression
--------------- -------------------
Kamis Kamis
Jumat Jumat
Sabtu Sabtu
Minggu Minggu
Sen Sen
Sel Sel
Rabu Rabu
Are you looking for an update statement? Because you have a SET in your select statement. If so, how about this?
UPDATE table_name
SET datecol = CASE
WHEN DATENAME(dw, datecol) = 'Monday' THEN 'Minggu'
WHEN DATENAME(dw, datecol) = 'Tuesday'
...
ELSE datecol
END;

Show Dates that have no values for selected column

I have the following query which counts the number of items created on a particular date in the last 10 days
SELECT
CONVERT (DATE, CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688) AS 'Logged Date',
Count (*) AS 'Total'
FROM
MTV_System$WorkItem$Incident
WHERE
CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688 >= DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 10, 0)
GROUP BY
CONVERT(DATE, CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688)
How do I get this to show the dates which have no values present (i.e. get every date value for the last 10 days, return the count if there is data or 0 if none). Using SQL Server 2012.
You can write a recursive cte to get the date for the last 10 days into a table as follows:
WITH TableA (StartDate) AS (SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 10, 0)),
q as (
SELECT StartDate
, Number = 0
FROM TableA
UNION ALL
SELECT DATEADD(d,1,StartDate)
, Number = Number + 1
FROM q
WHERE 10 > Number )
Then join q with your original query, to get a row for every date.
select q.StartDate, yourtable.Total from q
left join (
SELECT
CONVERT (DATE, CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688) AS 'Logged Date',
Count (*) AS 'Total'
FROM
MTV_System$WorkItem$Incident
WHERE
CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688 >= DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 10, 0)
GROUP BY
CONVERT(DATE, CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688)
) as yourtable on [Logged Date] = q.StartDate
Similar to BeanFrog's answer but a little shorter
-- sample data for testing
declare #MTV_System$WorkItemIncident table (
[CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688] DATE,
[Total] INT
);
INSERT INTO #MTV_System$WorkItemIncident VALUES ('2015-11-23', 23);
INSERT INTO #MTV_System$WorkItemIncident VALUES ('2015-11-21', 21);
INSERT INTO #MTV_System$WorkItemIncident VALUES ('2015-11-30', 30);
-- now the query
WITH TableA (LoggedDate) AS (
SELECT TOP 10 CONVERT (DATE, DATEADD(DAY, number * -1, GETDATE())) AS 'LoggedDate'
FROM master.dbo.spt_values
WHERE name IS NULL
)
SELECT TableA.[LoggedDate],
SUM(ISNULL(Data.Total, 0)) AS 'LoggedCount'
FROM TableA
LEFT JOIN #MTV_System$WorkItemIncident AS Data ON CONVERT (DATE, CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688) = TableA.[LoggedDate]
GROUP BY TableA.[LoggedDate]
Not that there is anything wrong with BeanFrog's answer, but if you don't want to use a recursive cte you could do this:
CREATE TABLE MTV_System$WorkItem$Incident (id int PRIMARY KEY, CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688 datetime)
INSERT INTO MTV_System$WorkItem$Incident VALUES (1, '20151201')
INSERT INTO MTV_System$WorkItem$Incident VALUES (2, '20151126')
INSERT INTO MTV_System$WorkItem$Incident VALUES (3, '20151127')
INSERT INTO MTV_System$WorkItem$Incident VALUES (4, '20151127')
SELECT
ReportDate AS 'Logged Date',
Count (CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688) AS 'Total'
FROM (
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 0, 0) AS ReportDate
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 1, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 2, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 3, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 4, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 5, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 6, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 7, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 8, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 9, 0)
UNION SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Getdate()) - 10, 0)
) AS Dates
LEFT JOIN MTV_System$WorkItem$Incident ON ReportDate = CONVERT(DATE, CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688)
GROUP BY ReportDate
BeanFrog's answer has the advantage of being able to easily change the number of days though.

MS SQL Convert date to short

I am trying to get all of the records from a table where the ExpiryDate field is exactly one month away.
The problem however is that the ExpiryDate is stored with the hours, minutes and seconds. How do I therefore say - Get me all of the records from my table where the ExpiryDate (dd/MM/yyyy) is one month ahead of now (dd/MM/yyyy).
This is what I have currently:
SELECT * FROM dbo.Custom_MembershipTransaction mt (nolock)
WHERE mt.ExpiryDate = DATEADD(MONTH, 1, GETDATE())
AND mt.IsComplete = 1;
You need some buffertime like
SELECT * FROM dbo.Custom_MembershipTransaction mt (nolock)
WHERE mt.ExpiryDate < DATEADD(MONTH, 1, GETDATE())
AND mt.ExpiryDate > DATEADD(DAY, -1, DATEADD(MONTH, 1, GETDATE()))
AND mt.IsComplete = 1;
This will get you all recors that have an expiredate between 1 month ahead an (1 month - 1 day) ahead.
SELECT * FROM dbo.Custom_MembershipTransaction mt (nolock)
WHERE mt.ExpiryDate >= DATEADD(DAY, DATEDIFF(DAY, 0, DATEADD(MONTH, 1, GETDATE())), 0)
AND mt.ExpiryDate < DATEADD(DAY, DATEDIFF(DAY, 0, DATEADD(MONTH, 1, GETDATE()) + 1), 0)
AND mt.IsComplete = 1;
I didn't make operation on ExpiryDate as it might be used by an index
Try this:
SELECT * FROM dbo.Custom_MembershipTransaction mt (nolock)
WHERE convert(varchar, mt.ExpiryDate, 102) = convert(varchar, DATEADD(MONTH, 1, GETDATE()),102)
AND mt.IsComplete = 1;

How to use SQL to do a group by with different dates?

Lets say I have a table with the following columns:
Qty, INTEGER
SaleDate, DATETIME
I would now like to see this result:
Sold in the last 7 days | Sold in last 14 days
-----------------------------------------------------
10 | 20
I can use a where clause to use between, however how would I get the qty sold for 7 and 14 days?
Filter in the WHERE clause to get days 0 to -14. Then aggregate on days 0 to -7 separately.
SELECT
...,
SUM(CASE WHEN SaleDate >= DATEADD(day, -7, GETDATE()) THEN 1 ELSE 0 END) AS 7days,
COUNT(*) AS 14days
FROM
MyTable
WHERE
SaleDate >= DATEADD(day, -14, GETDATE())
GROUP BY
...
Tested in MS T-SQL 2003
declare #whatever table(
qty int,
saledate datetime
)
insert into #whatever select 1, getdate()
insert into #whatever select 2, dateadd(dd, -1, getdate())
insert into #whatever select 2, dateadd(dd, -2, getdate())
insert into #whatever select 1, dateadd(dd, -3, getdate())
insert into #whatever select 1, dateadd(dd, -4, getdate())
insert into #whatever select 1, dateadd(dd, -5, getdate())
insert into #whatever select 1, dateadd(dd, -6, getdate())
insert into #whatever select 1, dateadd(dd, -7, getdate())
insert into #whatever select 1, dateadd(dd, -8, getdate())
insert into #whatever select 1, dateadd(dd, -9, getdate())
insert into #whatever select 2, dateadd(dd, -10, getdate())
insert into #whatever select 2, dateadd(dd, -11, getdate())
insert into #whatever select 1, dateadd(dd, -15, getdate())
insert into #whatever select 2, dateadd(dd, -16, getdate())
select
qty,
sum(
case
when datediff(dd, saledate, getdate()) between 0 and 7 then 1
else 0
end
) as [Sold in last 7 days],
sum(
case
when datediff(dd, saledate, getdate()) between 0 and 14 then 1
else 0
end
) as [Sold in last 14 days]
from
#whatever
group by
qty
;
select sum(Qty), datediff(w, getdate(), SaleDate) as Period
from table
group by datediff(ww, getdate(), SaleDate)