Looking at SQL Code for Validation - sql

I have two queries that appear to be the same. We are trying to get quarter today. One using a hard coded date and one not. One query is returning 2100 less records. The first and last record are the same. All of Feb match in both and the last 5 days in January match too.
Query 1 with hard coded date.
SELECT c.Account_RecordType
,timewait
,a.convotime
,DATENAME(Month, timewait) AS 'Mnth'
,DATENAME(year, timewait) AS 'yr'
,DATENAME(quarter, timewait) AS 'qrt'
FROM SalesForce.dbo.SalesForceContact AS b
INNER JOIN Dossier_Replication.dbo.vwSF_DATA_Contact c
ON b.ContactID = c.CONTACTID__C
RIGHT OUTER JOIN satVRS.dbo.rptNECACallHistory AS a
ON b.UserID = a.UserID_Caller
WHERE ( b.Platform = 'HandsonVRS' )
AND ( a.timeWait BETWEEN '2014-01-01' AND '2014-02-24' )
AND ( a.isReport = '1' )
AND ( a.NECA_isReport = '1' )
AND ( a.ConvoTime > '0' )
AND ( c.Account_RecordType = 'Enterprise Account' )
GROUP BY c.Account_RecordType
,timewait
,a.convotime
Second query is pulling quarter,year, and day from the date field in question.
SELECT c.Account_RecordType
,timewait
,a.convotime
,DATENAME(Month, timewait) AS 'Mnth'
,DATENAME(year, timewait) AS 'yr'
,DATENAME(quarter, timewait) AS 'qrt'
FROM SalesForce.dbo.SalesForceContact AS b
INNER JOIN Dossier_Replication.dbo.vwSF_DATA_Contact c
ON b.ContactID = c.CONTACTID__C
RIGHT OUTER JOIN satVRS.dbo.rptNECACallHistory AS a
ON b.UserID = a.UserID_Caller
WHERE ( b.Platform = 'HandsonVRS' )
AND ( a.timeWait BETWEEN '2014-01-01' AND '2014-02-24' )
AND ( a.isReport = '1' )
AND ( a.NECA_isReport = '1' )
AND ( a.ConvoTime > '0' )
AND ( c.Account_RecordType = 'Enterprise Account' )
GROUP BY c.Account_RecordType
,timewait
,a.convotime
Does any one see anything obviously wrong with these two. Any suggestions, I thank you in advance. We are running sql 2012

Sorry my bad, here is the second one...
select
c.Account_RecordType,timewait,a.convotime,(datename(year,timewait))as twy,(datename(quarter,timewait))as twq
FROM SalesForce.dbo.SalesForceContact AS b INNER JOIN
Dossier_Replication.dbo.vwSF_DATA_Contact c ON b.ContactID = c.CONTACTID__C RIGHT OUTER JOIN
satVRS.dbo.rptNECACallHistory AS a ON b.UserID = a.UserID_Caller
WHERE (b.Platform = 'HandsonVRS')
AND (datename(year,timewait))=(datename(year,getdate()-1)) AND (datename(quarter,timewait))=(datename(quarter,getdate()-1))
AND (a.isReport = '1')
AND (a.NECA_isReport = '1')
AND (a.ConvoTime > '0')
AND (c.Account_RecordType = 'Enterprise Account')
Group by c.Account_RecordType,timewait,a.convotime
Order by timewait

Related

Counting and grouping NULL and non NULL values with count results in separate columns

Really stumped on this one. I'm trying to figure out how i can get my SQL query shown below to do a count of null and not null aircraft ID's with a table of results that has two count columns, one for NULL aircraft IDs and another for Not NULL aircraft IDs and is grouped by operator, so it looks something like this:
SELECT DISTINCT org.organization "operator",
ah.aircraft_registration_country "country",
ah.aircraft_registration_region "region",
acl.aircraft_master_series "aircraft type",
ah.publish_date "publish date",
f.aircraft_id "aircraft_id"
FROM ((((("flights"."tracked_utilization" f
left join "pond_dataops_analysis"."latest_aircraft" a
ON ( a.aircraft_id = f.aircraft_id ))
left join fleets.aircraft_all_history_latest ah
ON ( ( ( ah.aircraft_id = f.aircraft_id )
AND ( Coalesce(f.actual_runway_departure_time_local,
actual_gate_departure_time_local,
published_gate_departure_time_local) >=
ah.start_event_date ) )
AND ( Coalesce(f.actual_runway_departure_time_local,
actual_gate_departure_time_local,
published_gate_departure_time_local) <
ah.end_event_date ) ))
left join fleets.organizations_latest org
ON ( org.organization_id = ah.operator_organization_id )))
left join fleets.aircraft_usage_history_latest ash
ON ( ( ( ( ash.aircraft_id = f.aircraft_id )
AND ( start_event_date >= ash.usage_start_date ) )
AND ( start_event_date < ash.usage_end_date ) )
AND ( aircraft_usage_classification = 'Primary' ) )
left join fleets.aircraft_configuration_history_latest accl
ON ash.aircraft_id = accl.aircraft_id
left join fleets.aircraft_configurations_latest acl
ON accl.aircraft_configuration_id = acl.aircraft_configuration_id
)
WHERE (((( f.flight_departure_date > ( "Now"() - interval '90' day ) ))))
Not sure how to do a 'count/group by' so that the query can show what i'm after.
Regards,
Mark
Something like this:
select
x, y, z,
sum( case when aircraft_id is null then 1 else 0 end ) as null_cnt,
sum( case when aircraft_id is null then 0 else 1 end ) as notnull_cnt
from
(inline subquery)
group by
x, y, z
FWIW, you don't need all those parentheses in your query, they are unnecessary and more confusing than helpful. They do have their place in some cases, especially when dealing with "OR" conditions, but for this query they are completely superfluous:
FROM
"flights"."tracked_utilization" f
left join "pond_dataops_analysis"."latest_aircraft" a
ON a.aircraft_id = f.aircraft_id
left join fleets.aircraft_all_history_latest ah
ON ah.aircraft_id = f.aircraft_id
AND Coalesce(f.actual_runway_departure_time_local, actual_gate_departure_time_local, published_gate_departure_time_local) >= ah.start_event_date
AND Coalesce(f.actual_runway_departure_time_local, actual_gate_departure_time_local, published_gate_departure_time_local) < ah.end_event_date
left join fleets.organizations_latest org
ON org.organization_id = ah.operator_organization_id
left join fleets.aircraft_usage_history_latest ash
ON ash.aircraft_id = f.aircraft_id
AND start_event_date >= ash.usage_start_date
AND start_event_date < ash.usage_end_date
AND aircraft_usage_classification = 'Primary'
left join fleets.aircraft_configuration_history_latest accl
ON ash.aircraft_id = accl.aircraft_id
left join fleets.aircraft_configurations_latest acl
ON accl.aircraft_configuration_id = acl.aircraft_configuration_id
WHERE
f.flight_departure_date > "Now"() - interval '90' day

How to get biggest value from 2 or more fields in a subquery

I have a table with customers that I join with a fact table with sales, based on invoices.
What I need from my report is to get in first part the biggest value of sales based on the incoming order type (1,2,3,C,D) for a customer for last year. And in the second part to get the same but for current year. What I get as result from my current query is all incoming order types with the customer revenue made for each of them. I tried with outer apply as subquery to get only the top 1 value ordered by revenue descending, but in the result I get the same - For all order types the customer revenue. Please help! I hope my explanation isn't understood only by me (happens a lot..)
use dwh01;
WITH OrderTypeUsedLY AS
(
SELECT
c.CustomerKey
,c.BranchId
,c.CustomerId
,c.CustomerName
,ISNULL(SUM(y.[Sale_Revenue]), 0) as [Sale_Revenue_LY]
,ISNULL(SUM(y.[Sale_GrossMarginTotal]), 0) as [Sale_GrossMarginTotal_LY]
,y.IncomingOrderTypeId as IncomingOrderType_LY
FROM live.DimCustomer c
left join (SELECT s.CustomerKey,iot.IncomingOrderTypeid, s.[Sale_Revenue], s.[Sale_GrossMarginTotal] FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d
on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType iot on iot.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where s.ReportCurrencyId = 'LC'
and D.Year = YEAR(GETDATE())-1 --- Last Year
) y on c.CustomerKey = y.CustomerKey
where c.CustomerKey = '157053'
group by c.CustomerKey, c.CustomerId, c.CustomerName, c.BranchId, y.IncomingOrderTypeId
),
--*********************************************************************************************************************************--
OrderTypeCY as(
SELECT
c.CustomerKey
,c.BranchId
,c.SalesRepKey
,c.CustomerId
,c.CustomerName
,ISNULL(SUM(y.[Sale_Revenue]), 0) as [Sale_Revenue_CY]
,ISNULL(SUM(y.[Sale_GrossMarginTotal]), 0) as [Sale_GrossMarginTotal_CY]
,y.IncomingOrderTypeId as IncomingOrderType_CY
FROM live.DimCustomer c
left join (SELECT s.CustomerKey,iot.IncomingOrderTypeid, s.[Sale_Revenue], s.[Sale_GrossMarginTotal] FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d
on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType iot on iot.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where s.ReportCurrencyId = 'LC'
and D.Year = YEAR(GETDATE()) --- Current Year
) y on c.CustomerKey = y.CustomerKey
where c.CustomerKey = '157053'
group by c.CustomerKey, c.CustomerId, c.CustomerName, c.BranchId, y.IncomingOrderTypeId, c.SalesRepKey
)
--*********************************************************************************************************************************--
SELECT
otly.BranchId,
rep.SalesRepId,
rep.SalesRepName,
otly.CustomerId,
otly.CustomerName,
otly.Sale_Revenue_LY,
otly.Sale_GrossMarginTotal_LY,
IncomingOrderType_LY,
otcy.Sale_Revenue_CY,
otcy.Sale_GrossMarginTotal_CY,
IncomingOrderType_CY
from OrderTypeUsedLY otly
left join OrderTypeCY otcy
on otly.CustomerKey = otcy.CustomerKey
join live.DimCustomer cus on cus.CustomerKey = otcy.CustomerKey
join live.DimSalesRep rep on rep.SalesRepKey = otcy.SalesRepKey
order by otcy.Sale_Revenue_CY desc, otly.Sale_Revenue_LY desc
,rep.SalesRepId
And here is the outer apply I tried:
outer apply (
SELECT top 1
iot.IncomingOrderTypeId,
Sale_Revenue
FROM [dwh01].[live].DimIncomingOrderType iot
where iot.IncomingOrderTypeKey = y.IncomingOrderTypeKey
order by Sale_Revenue desc) x
In the first select ( with OrderTypeUsed_LY ) I get this:
And I get the same in the second select, but with the values for current year.
The purpose of the report is to see the difference in the incoming order type most used (most profit made with it) for a customer last year and to see if he continues to use it this year, or uses another incoming order type this year.
Again I'm sorry for the bad explanation, I'm trying my best (I understand myself very well)
Here is the expected result:
Expected Result
I marked in red the last year part and in green the current year part.
If you change the subquery to:
SELECT
iot.IncomingOrderTypeKey,
MAX(Sale_Revenue)
FROM [dwh01].[live].DimIncomingOrderType iot
GROUP BY iot.IncomingOrderTypeKey
then you can JOIN (not APPLY) directly on IncomingOrderTypeKey AND Sale_Revenue.
Try this:
USE dwh01;
DECLARE #CustomerKey varchar(6) = '157053'
, #ReportCurrencyId varchar(2) = 'LC'
, #CurrentYear int = YEAR(GETDATE())
, #TargetYear int = YEAR(GETDATE())-1
;
WITH FactsTable AS
(
SELECT
s.CustomerKey
, i.IncomingOrderTypeid
, [Sale_Revenue] = ISNULL(s.[Sale_Revenue] , 0)
, [Sale_GrossMarginTotal] = ISNULL(s.[Sale_GrossMarginTotal], 0)
, d.[Year]
FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType i on i.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where
s.CustomerKey = #CustomerKey
and s.ReportCurrencyId = #ReportCurrencyId
)
, OrderTypeTable
(
SELECT
c.CustomerKey
, c.BranchId
, c.CustomerId
, c.CustomerName
, c.SalesRepKey
, IncomingOrderType_LY = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.IncomingOrderTypeId ELSE 0 END)
, [Sale_Revenue_LY] = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.[Sale_Revenue] ELSE 0 END)
, [Sale_GrossMarginTotal_LY] = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.[Sale_GrossMarginTotal] ELSE 0 END)
, IncomingOrderType_LY = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.IncomingOrderTypeId ELSE 0 END)
, [Sale_Revenue_CY] = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.[Sale_Revenue] ELSE 0 END)
, [Sale_GrossMarginTotal_CY] = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.[Sale_GrossMarginTotal] ELSE 0 END)
FROM live.DimCustomer c
left join FactsTable y on y.CustomerKey = c.CustomerKey
group by
c.CustomerKey
, c.BranchId
, c.CustomerId
, c.CustomerName
, y.IncomingOrderTypeId
, c.SalesRepKey
)
SELECT
O.BranchId
, R.SalesRepId
, R.SalesRepName
, O.CustomerId
, O.CustomerName
, O.Sale_Revenue_LY
, O.Sale_GrossMarginTotal_LY
, O.IncomingOrderType_LY
, O.Sale_Revenue_CY
, O..Sale_GrossMarginTotal_CY
, O.IncomingOrderType_CY
from OrderTypeTable O
join live.DimSalesRep R on R.SalesRepKey = O.SalesRepKey
order by
O.Sale_Revenue_CY desc
, O.Sale_Revenue_LY desc
, R.SalesRepId
The solution is with using row_number() function in the inner query of the first CTE:
(
select *, row_number() over (partition by x0.CustomerKey order by x0.Sale_Revenue desc) as rn
from
(
select fs.CustomerKey, iot.IncomingOrderTypeKey,
sum(fs.Sale_Revenue) as Sale_Revenue
FROM [dwh01].[live].DimIncomingOrderType iot
join live.FactSales fs
on iot.IncomingOrderTypeKey = fs.IncomingOrderTypeKey
join live.DimDate d
on d.DateId = fs.PostingDateKey
where d.[year] = #CurrentYear
GROUP BY fs.CustomerKey, iot.IncomingOrderTypeKey
) as x0
) as x1 on x1.CustomerKey = s.CustomerKey
The row_number() function gets only the first row from the result for each customer, and that is with the biggest sale revenue ( order by sale_revenue desc).

Access query only return 1 max date result per select MAX statement

I've been beating my head for a while on this one...
I'm working with a legacy Access database (which I'm working on phasing out/replacing), and an issue came up where duplicate records are now showing from the query where we used to never see duplicate records.
We pull expiration dates from several tables, and the query returns the most future expiration date for each person, for each certificate they have.
The whole query is quite large, but the problem area, that is left join duplicated for each table of expirations, is this:
SELECT Courses.[id], Person.FirstName, Person.MiddleName, Person.LastName, Courses.Code, Codes.Name, Courses.Date, Courses.[P/F/I/C], Courses.ExpirationDate, Courses.Grade
FROM Codes INNER JOIN (Courses INNER JOIN Person ON Courses.[id] = Person.[id]) ON Codes.Code = Courses.Code
WHERE (
Courses.ExpirationDate = (SELECT MAX(ExpirationDate) FROM Courses b WHERE b.ExpirationDate >= Date() AND (b.[id] = Courses.[id]) AND b.Code = 'c0' AND ((b.[P/F/I/C])='P' Or (b.[P/F/I/C])='C'))
) OR (
Courses.ExpirationDate = (SELECT MAX(ExpirationDate) FROM Courses b WHERE b.ExpirationDate >= Date() AND (b.[id] = Courses.[id]) AND b.Code = 'c1' AND ((b.[P/F/I/C])='P' Or (b.[P/F/I/C])='C'))
) OR (
Courses.ExpirationDate = (SELECT MAX(ExpirationDate) FROM Courses b WHERE b.ExpirationDate >= Date() AND (b.[id] = Courses.[id]) AND b.Code = 'c2' AND ((b.[P/F/I/C])='P' Or (b.[P/F/I/C])='C'))
) OR (
Courses.ExpirationDate = (SELECT MAX(ExpirationDate) FROM Courses b WHERE b.ExpirationDate >= Date() AND (b.[id] = Courses.[id]) AND b.Code = 'c3' AND ((b.[P/F/I/C])='P' Or (b.[P/F/I/C])='C'))
) OR (
Courses.ExpirationDate = (SELECT MAX(ExpirationDate) FROM Courses b WHERE b.ExpirationDate >= Date() AND (b.[id] = Courses.[id]) AND b.Code = 'c4' AND ((b.[P/F/I/C])='P' Or (b.[P/F/I/C])='C'))
) OR (
Courses.ExpirationDate = (SELECT MAX(ExpirationDate) FROM Courses b WHERE b.ExpirationDate >= Date() AND (b.[id] = Courses.[id]) AND b.Code = 'c5' AND ((b.[P/F/I/C])='P' Or (b.[P/F/I/C])='C'))
) OR (
Courses.ExpirationDate = (SELECT MAX(ExpirationDate) FROM Courses b WHERE b.ExpirationDate >= Date() AND (b.[id] = Courses.[id]) AND b.Code = 'c6' AND ((b.[P/F/I/C])='P' Or (b.[P/F/I/C])='C'))
) OR (
Courses.ExpirationDate = (SELECT MAX(ExpirationDate) FROM Courses b WHERE b.ExpirationDate >= Date() AND (b.[id] = Courses.[id]) AND b.Code = 'c7' AND ((b.[P/F/I/C])='P' Or (b.[P/F/I/C])='C'))
)
ORDER BY Courses.[id], Courses.Code
If one of those OR clauses has two future expiration dates for a single person in a single class (they re-certified before they expired), the query returns both records. It should only return the MAX of those two records. Any ideas as to what I'm missing in the above query? I can post the rest of the query that this one is nested in if it helps, but I'm pretty sure this is where the issue is.
I am guessing that you really want this:
WHERE Courses.ExpirationDate = (SELECT MAX(b.ExpirationDate)
FROM Courses b
WHERE b.ExpirationDate >= Date() AND
b.[id] = Courses.[id] AND
b.Code IN ('c0', 'c1', . . .) AND
b.Code = Courses.Code AND
b.[P/F/I/C]) IN ('P', 'C')
)
This is a single condition with an additional correlation condition on Code.

not able to select a column outside left join

I am working with the below query
SELECT * FROM
(SELECT DISTINCT
a.Number
,a.Description
,ISNULL(temp.Quantity,0) Quantity
,LastReceived
,LastIssued
FROM Article a
LEFT JOIN (
select ss.ArticleId
, ss.Quantity
, max(lastreceiveddate) as LastReceived
, max(lastissueddate) as LastIssued
from StockSummary ss
where ss.UnitId = 8
group by ss.ArticleId, ss.StockQuantity
having (MAX(ss.LastReceivedDate) < '2014-09-01' or MAX(ss.LastReceivedDate) is NULL)
AND (MAX(ss.LastIssuedDate) < '2014-09-01' or MAX(ss.LastIssuedDate) is NULL)
) temp on a.Id = temp.ArticleId
WHERE a.UnitId = 8
) main
ORDER BY main.Number
What i want to achieve is to select the articles only with the MAX(ss.LastReceivedDate) and MAX(ss.LastIssuedDate) condition in the Left join query and then do the Quantity Select in the main query.
Note: the quantity column can be 0 or NULL.
Kindly help

How to Optimize this query (stuff part)

How can I Optimize this following query:
SELECT
MONTH('1' + LEFT(Datename(month,visitDate),3) +'00') AS MONTH_NUMBER ,
VisitMonth = LEFT(Datename(month,visitDate),3)
,TotalVisits = Count(v.VisitID)
,TotalVisits_with_StandardReport = Count(CASE WHEN v.ReportStandard NOT IN (0,9) THEN v.ReportStandard END)
,TotalVisits_with_FeedbackReport = Count(CASE WHEN v.DiscrepancyType IN (2,5) THEN v.DiscrepancyStatus END)
,Perc =
CAST(100 - ISNULL(CAST((Count(CASE WHEN v.DiscrepancyType IN (2,5) THEN v.DiscrepancyType END) * 1.0 / Count(CASE WHEN v.ReportStandard NOT IN (0,9) THEN v.ReportStandard END)) * 100 AS FLOAT),0) AS NUMERIC(10,2))
,VisitAssignmentID_with_FeedbackRpt = STUFF (( SELECT ', ' + CAST(v2.AssignmentID AS VARCHAR) from Visits v2
INNER JOIN
Assignments a2 ON a2.AssignmentID = v2.AssignmentID
WHERE
DATENAME(MONTH,v.VisitDate) = DATENAME(MONTH,v2.VisitDate)
AND a2.ClientID IN (22,33) AND v2.DiscrepancyType IN (2,5)
GROUP BY V2.AssignmentID
FOR xml path('')), 1, 2, '')
FROM Visits v
INNER JOIN Assignments a ON a.AssignmentID = v.AssignmentID
WHERE a.ClientID IN (22,33)
AND v.VisitDate BETWEEN '01/01/2013' AND '31/12/2013'
GROUP BY DATENAME(MONTH,v.VisitDate)
ORDER BY MONTH_NUMBER
Result
Second query which i tried to simplify and optimize (but query results are not same)
I have tried to optimize the query and tried to simply the stuff inner query but i am not getting the results i want. It has reduced the total execution time though but results are not same.
WITH ALL_CTE(MONTH_NUMBER,VisitMonth,VisitID,AssignmentID,ReportStandard,DiscrepancyStatus,DiscrepancyType,VisitA ssignmentID_with_FeedbackRpt)
AS
-- Define the CTE query.
(
SELECT
MONTH('1' + LEFT(Datename(month,visitDate),3) +'00') AS MONTH_NUMBER ,
VisitMonth = LEFT(Datename(month,visitDate),3)
,v.VisitID, v.AssignmentID , v.ReportStandard , v.DiscrepancyStatus, v.DiscrepancyType
,VisitAssignmentID_with_FeedbackRpt =
STUFF (( SELECT ', ' + CAST((CASE WHEN DiscrepancyType IN (2,5) THEN v.AssignmentID END) AS VARCHAR)
FOR xml path('')), 1, 2, '')
FROM Visits v
INNER JOIN Assignments a ON a.AssignmentID = v.AssignmentID
WHERE a.ClientID IN (22,33)
AND v.VisitDate BETWEEN '01/01/2013' AND '31/12/2013'
group by v.AssignmentID,visitDate,VisitID,ReportStandard,DiscrepancyStatus,DiscrepancyType
)
-- Define the outer query referencing the CTE name.
SELECT
MONTH_NUMBER
,VisitMonth
,COUNT(VisitID)
,TotalVisits_with_StandardReport = COUNT(CASE WHEN ReportStandard NOT IN (0,9) THEN ReportStandard END)
,TotalVisits_with_FeedbackReport = COUNT(CASE WHEN DiscrepancyType IN (2,5) THEN DiscrepancyStatus END)
,isnull(VisitAssignmentID_with_FeedbackRpt,0)
FROM ALL_CTE
GROUP BY MONTH_NUMBER,VisitMonth,VisitAssignmentID_with_FeedbackRpt
Client Stats
I think the only real optimization you can do here is make sure that you have an index on AssignmentID so that the inner join is quicker. All the other parts are pretty irrelevant, they are just conversions handled in memory.