Incremental Load Issue - sql

I have a query like so:
SELECT Col1, Col2, Col3, ColDate
FROM TableA
WHERE DAY(ColDate) = 1
AND MONTH(ColDate) = MONTH(CASE WHEN DATEPART(HOUR, GETDATE()) < 16 THEN GETDATE() - 1 ELSE GETDATE()END)
AND YEAR(ColDate) = YEAR(CASE WHEN DATEPART(HOUR, GETDATE()) < 16 THEN GETDATE() - 1 ELSE GETDATE()END)
The query above pulls data daily into another table. Now, the issue with this query is that we have to manually change the DAY(ColDate) =? in the WHERE Clause everyday to pull the right data. How do I set my WHERE Clause to check the day in that month and pull data accordingly?

Is this what you are looking for?
WHERE DAY(colDate) = DAY(GETDATE()) AND
. . .
Or, perhaps:
WHERE DAY(colDate) = DAY(CASE WHEN DATEPART(HOUR, GETDATE()) < 16 THEN GETDATE() - 1 ELSE GETDATE() END) AND

Related

Possible Pivot in SQL

I'm trying to fetch the data from a DB to get number of Unused Applications for 60 days and 90 Days. I've tried the below:
SELECT
Uname AS [User ID],
AppName As [Application],
COUNT(*) AS [Unused App for 60 Days]
FROM APPTABLE
WHERE LAST_USE<getutcdate()-60
GROUP BY Uname, AppNameNow
I want to do the same for 90 days as well but in this same query. I'm having difficulty in doing it.
Could you help me understand how to do it? Appreciate your response.
Use conditional aggregation. I would suggest using dateadd() to be explicit about the intention of the logic:
SELECT Uname AS [User ID], AppName As [Application],
SUM(CASE WHEN LAST_USE < DATEADD(DAY, -60, getutcdate()) THEN 1 ELSE 0 END) as unused_60,
SUM(CASE WHEN LAST_USE < DATEADD(DAY, -90, getutcdate()) THEN 1 ELSE 0 END) as unused_90
FROM APPTABLE
WHERE LAST_USE < DATEADD(DAY, -60, getutcdate())
GROUP BY Uname, AppNameNow
Note that the WHERE clause is still filtering the dates. But you need to be careful that the WHERE is consistent with the time frames in the SELECT.
count(*) is logically equivalent to sum(1).
Instead, use a conditional case:
sum(case when LAST_USE<getutcdate()-60 then 1 else 0 end) as [Unused App for 60 Days]
,sum(case when LAST_USE<getutcdate()-90 then 1 else 0 end) as [Unused App for 90 Days]
of course, include the larger set in your where

How to set flag for time interval in T-SQL

I have a query that has InsertDate and flag field. I need to set the flag to Y for the first 10 minutes, and every 12 hours after that. This is what I have so far, but hard-coded is not an ideal at all.
select InsertDate, case when DATEDIFF(MINUTE, MAX(InsertDate),
GETDATE()) <= 10 then 'Y' when DATEDIFF(MINUTE, MAX(InsertDate),
GETDATE()) = 720 then 'Y' when DATEDIFF(MINUTE, MAX(InsertDate),
GETDATE()) = 1440 then 'Y' Else 'N' end as flag
How do I update my syntax to get away from hard-coded? Thank you for any helps
Your query is not valid SQL to start with: it has no from clause, and having both insertdate and max(insertdate) in the select clause makes no sense.
Bottom line, I think you want modulo artithmetics:
case
when datediff(minute, insertdate, getdate()) <= 10 then 'y'
when datediff(minute, insertdate, getdate()) % 720 = 0 then 'y'
else 'n'
end as flag
<expr> % 720 = 0 reads as: <expr> is a multiple of 720.

CASE in WHERE Clause

Below is my current SQL Server 2012 query. Basically I want the information from the last business day, but on Monday, I want it to pull Friday's info instead of Sunday. This is what I have so far in my query but it won't accept it.
USE [LetterGeneration]
SELECT
g.LetterGenerationPrintJobId,
CONVERT(CHAR(12), r.CreatedDate, 101) AS CreatedDate,
YEAR(r.CreatedDate) AS Year,
MONTH(r.CreatedDate) AS Month,
DAY(r.CreatedDate) AS Day,
CASE
WHEN DATEPART(dw, r.CreatedDate) = 1
THEN 1
WHEN DATEPART(dw, r.CreatedDate) = 7
THEN 1
ElSE 0
END AS Weekend,
s.LetterGenerationStatusId AS Status,
COUNT(g.LetterGenerationId) AS LetterCount,
SUM(g.LetterPageCount) AS PageCount,
t.IsLitigationCoverLetterAllowed,
CASE
WHEN g.CarrierTrackingNumber LIKE '%1ZE%'
THEN 1
WHEN g.CarrierTrackingNumber LIKE '921489%'
THEN 2
WHEN g.CarrierTrackingNumber LIKE '917190%'
THEN 2
ELSE 3
END AS CarrierType
FROM
[LetterGenerationTemplateRequest] AS R
INNER JOIN
[LetterGenerationTemplate] AS T ON t.[LetterGenerationTemplateId] = r.LetterGenerationTemplateId
INNER JOIN
LetterGeneration G ON g.LetterGenerationTemplateRequestId = r.LetterGenerationTemplateRequestId
INNER JOIN
LetterGenerationStatus S ON g.LetterGenerationStatusId = s.LetterGenerationStatusId
WHERE
(CASE
WHEN (DATENAME(dw,GETDATE()) = 'Monday')
THEN (DATEDIFF(d, r.CreatedDate, GETDATE()) = 3)
ELSE (DATEDIFF(d, r.CreatedDate, GETDATE()) = 1)
END)
AND t.[TemplateKey] NOT LIKE '%PLTV1%'
AND s.LetterGenerationStatusId = 19
ORDER BY
r.CreatedDate DESC, g.LetterGenerationPrintJobId DESC
What am I missing or misunderstanding about my WHERE clause in order to make it work in the way I'm thinking?
Thanks
Maybe convert to a regular AND/OR?
WHERE (
((DATENAME(dw,GETDATE()) = 'Monday') AND (DATEDIFF(d, r.CreatedDate, GETDATE()) = 3))
OR
(DATEDIFF(d, r.CreatedDate, GETDATE()) = 1)
)
....
What am I missing or misunderstanding about my WHERE clause in order to make it work in the way I'm thinking?
Though you haven't given the error message you're getting, I'm sure it's syntax related because you're putting the test INSIDE the result of the case, not outside it
You're writing:
WHERE CASE WHEN it_is_monday THEN data_date = friday ELSE data_date = yesterday END
You should be writing:
WHERE data_date = CASE WHEN it_is_monday THEN friday ELSE yesterday END
Essentially: you're not supposed to use case/when in a where clause to do your "column = something" comparison and return you true or false, you're supposed to use it to just return the "something" you compare against "column" else in order to get your true or false
The other answers focus on "giving you a working solution"; this answer focuses on telling you what was going wrong with your thought processes re your original query
Here's a simpler example:
--wrong syntax to search a table full of cats (4 legs) and people (2 legs)
WHERE CASE WHEN animal_type = 'cat' THEN legs = 4 ELSE legs = 2 END
--right syntax
WHERE limbs = CASE WHEN animal_type = 'cat' THEN 4 ELSE 2 END
Ignoring holidays for a second, and assuming you have at least one record for every date, something like this should work.
where cast(createdDate as date) =
(select max(createdDate )
from table
where createdDate < cast(getDate() as date
and dateName(dw, createdDate in ('Monday' etc)
)
In order to maintain SARGability(able to do a seek against an index) you want to make sure the table columns in the predicate aren't included in any functions.
The following should work and maintain SARGability...
WHERE
r.CreatedDate = CASE
WHEN DATEPART(dw, getdate) = 2
THEN DATEADD(dd, -3, CAST(GETDATE() AS DATE))
ELSE CAST(GETDATE() AS DATE)
END
HTH,
Jason

SQL Server query, remove date dimension

I need help in removing the date dimension from the query below. In other words make the query independent of the date / time interval
My goal is to load the table into SSAS so that i would not have to change the date every time i run reports.
the query is huge (months, quarters, years, and aggregated date CR12,PR12 ...), i just gave a short example below
I sincerly appreciate any help
drop table #tmptmp
SELECT *, (DATEDIFF(day, enrollmentsDate, ShipmentDate))
- ((DATEDIFF(WEEK, enrollmentsenttDate, InitialShipmentDate) * 2)
+(CASE WHEN DATENAME(DW, enrollmentsentDate) = 'Sunday' THEN 1 ELSE 0 END)
+(CASE WHEN DATENAME(DW, ShipmentDate) = 'Saturday' THEN 1 ELSE 0 END)
- (select count(*) from tblFactoryHolidayDates where Date >= enrollmentsentDate
and Date < InitialShipmentDate)) as countdays into #tmptmp from
#tmpTouchpointsEnrollments
where EnrollmentSentDate is not null
----------------------------
drop table #tmp
select * into #tmp
from #tmptmp
where countdays < 20
drop table #tmpMetric
Select 'GrandTotal' as Dummy,'Avg days' as Metrics,'1' as MetricOrder,
Sum(case when Year(EnrollmentReceiveddate) ='2010' then (countdays) end) *1.0/
count(case when Year(EnrollmentReceiveddate) ='2010' then (patientID) end) *1.0 as Y2010,
into #tmpMetric
from #tmp
Thank you very much

Returning multiple queries as a single result set against the same database columns

So I am trying to create a report which will give me a count of sales orders and compare them to a previous date ranges. unfortunately I am not sure how to approach returning the results as each of these calculations are ran against the same table column.
Ideally my output would look something like this, including the NULL values
partner Today LastYear TwoYear
------- ------ -------- --------
zzz 10 15 4
yyy 2 4
xxx 3 1 2
I have the basic idea down:
DECLARE #currentDay DATETIME
SET #currentDay = DATEDIFF(day,0,GETDATE()) -- Gives it 00:00:00.000 for time
-- Todays orders
SELECT count(s.po_id) as 'Orders Today',c.tp_name
FROM [EDI_001].[dbo].[303v850h] as s
join [EDI_001].[dbo].[Trade] as c
on s.TP_PartID = c.TP_PartID
where s.ExportDate < #currentDay AND
s.ExportDate > DATEADD(day,-1,#currentDay)
group by c.tp_name
order by c.tp_name;
-- Last Years Day's orders
SELECT count(s.po_id) as 'Orders Today',c.tp_name
FROM [EDI_001].[dbo].[303v850h] as s
join [EDI_001].[dbo].[Trade] as c
on s.TP_PartID = c.TP_PartID
where s.ExportDate < DATEADD(year,-1,#currentDay) AND
s.ExportDate > DATEADD(year, -1,DATEADD(day,-1,#currentDay))
group by c.tp_name
order by c.tp_name;
I'll go ahead and stop there, as you can see the queries are almost identical just changing the date range in the where clause. What I don't know is how to combine the two queries into a single result set. As well, my join does not return the empty sets in either query. I realize that it won't with the current join used, however it hasn't shown in different results with left outer joins either... But realistically one problem at a time and the first step is to get a single result set. Any help would be greatly appreciated.
DECLARE #currentDay DATETIME
SET #currentDay = DATEDIFF(day,0,GETDATE()) -- Gives it 00:00:00.000 for time
SELECT Sum(
CASE
WHEN s.ExportDate Between DATEADD(day,-1,#currentDay) AND #currentDay
THEN 1
ELSE 0
END
) As Today,
Sum(
CASE
WHEN s.ExportDate Between DATEADD(year, -1,DATEADD(day,-1,#currentDay)) AND DATEADD(year,-1,#currentDay)
THEN 1
ELSE 0
END
) As LastYear,
Sum(
CASE
WHEN s.ExportDate Between DATEADD(year, -2,DATEADD(day,-1,#currentDay)) AND DATEADD(year,-2,#currentDay)
THEN 1
ELSE 0
END
) As TwoYear,
c.tp_name
FROM [EDI_001].[dbo].[303v850h] as s
JOIN [EDI_001].[dbo].[Trade] as c
on s.TP_PartID = c.TP_PartID
GROUP BY c.tp_name
ORDER BY c.tp_name;
You are looking for the UNION operator.
It's used to combine the result-set of two or more SELECT statements.
http://www.w3schools.com/sql/sql_union.asp
You can use a conditional aggregate:
SELECT c.tp_name,
Today = COUNT(CASE WHEN s.ExportDate > DATEADD(DAY,-1,#currentDay) THEN s.po_id END),
LastYear = COUNT(CASE WHEN s.ExportDate > DATEADD(YEAR,-1,#currentDay)
AND s.ExportDate < DATEADD(YEAR, -1,DATEADD(DAY, -1, #currentDay))THEN s.po_id END),
TwoYear = COUNT(CASE WHEN s.ExportDate > DATEADD(YEAR,-2, #currentDay)
AND s.ExportDate < DATEADD(YEAR, -2, DATEADD(DAY, -1, #currentDay))THEN s.po_id END),
FROM [EDI_001].[dbo].[303v850h] as s
JOIN [EDI_001].[dbo].[Trade] as c
ON s.TP_PartID = c.TP_PartID
WHERE s.ExportDate < #currentDay AND
s.ExportDate > DATEADD(YEAR, -2, DATEADD(DAY, -1, #currentDay))
GROUP BY c.tp_name
ORDER BY c.tp_name;
So you are essentially moving each of your WHERE clauses to a CASE statement inside the the COUNT, so you will only count records where your criteria is met.