How can I replicate a query to pull data side by side? - sql

I have the following query, and what I am trying to do is take the query data, replicate it but change the names on the column headers from FY14 Q1 to FY14 Q2 and change the filters in the query.
Is there a way I can have this data shown all in one big table by combining the different queries??? Please help.
Select H.OpportunityID, H.CREATEDDATE, H.STAGENAME as 'Q1-14 Stage', H.CLOSEDATE as 'Q1-14 Close Date'
From
(SELECT
OpportunityID, Max(CREATEDDATE) as MaxDate
FROM [BVSFWarehouse].[dbo].[sf_OPPORTUNITYHISTORY]
WHERE
CREATEDDATE <= '2013-05-01'
GROUP BY
OpportunityID) X
Join [BVSFWarehouse].[dbo].[sf_OPPORTUNITYHISTORY] H ON H.OpportunityID = X.OpportunityID
And X.MaxDate = H.CREATEDDATE

Related

SQL Query to Find if (Count of date > X) = 0 For Group of ID

I apologize if the title is not be correct as I'm not sure what I need to ask for, since I don't know how to build the query.
I have the following query built to return a list of chemicals and other related fields.
SELECT DISTINCT
RDB.Chemical_Record.[Chemical_ID],
RDB.Chemical_Record.[Expires_Date],
RDB.Assay_Group.[Assay_Group_Name] AS [Assay Group],
RDB.Chemical.[Chemical_Name],
RDB.Chemical.[Product_Number],
RDB.Chemical_Record.[Lot_Number],
RDB.Storage_Location.[Location_Name]
FROM RDB.Chemical_Record
LEFT JOIN RDB.Chemical ON Chemical_Record.[Chemical_ID] = Chemical.[ID_Chemical]
LEFT JOIN RDB.Storage_Location ON Storage_Location.[ID_Storage_Location] = Chemical_Record.[Storage_Location_ID]
LEFT JOIN RDB.Chemical_To_AGroup ON Chemical_To_AGroup.[Chemical_ID] = Chemical_Record.[Chemical_ID]
LEFT JOIN RDB.Assay_Group ON Assay_Group.[ID_Assay_Group] = Chemical_To_AGroup.[Assay_Group_ID]
WHERE RDB.Chemical_Record.[Expires_Date] >= DATEADD(day,-60, GETDATE())
ORDER BY RDB.Chemical_Record.[Chemical_ID], RDB.Chemical_Record.[Expires_Date], RDB.Assay_Group.[Assay_Group_Name]
I am using this query in a VB.Net application where it exports the results to an Excel worksheet and then performs additional actions to delete the rows I don't need. The process to query is quick, but working with Excel from .Net is painful and slow.
Instead I'd like to build the query to return the exact results I want, which I think is possible, I just can't figure out how. I have tried using a combination of Count, Group and Having, but since I've never worked with those I can't get them to work for me.
Example:
SELECT
COUNT(RDB.Chemical_Record.[Chemical_ID]) Count_ID,
RDB.Chemical_Record.[Chemical_ID],
RDB.Chemical_Record.[Expires_Date]
FROM RDB.Chemical_Record
WHERE RDB.Chemical_Record.[Expires_Date] > DATEADD(day,30,GETDATE())
GROUP BY RDB.Chemical_Record.[Chemical_ID], RDB.Chemical_Record.[Expires_Date]
ORDER BY RDB.Chemical_Record.[Chemical_ID]
As you can see from this example, it doesn't return the count of ID's where Expiration Date > DATEADD(day,30,GETDATE()) nor does it return the ID's that I actually wanted.
What I need to return is all chemicals (ID) that DO NOT have an expiration date > Today + 30 for that specific ID. The screenshot below shows an example of the data that gets pulled. The yellow highlighted rows are the only two in that set that should get returned as there are no other chemicals of those two ID's with an expiration date > Today + 30. All the other ID's should not show up since they DO have ID's of COUNT(Expiration Date > Today + 30) > 0.
If someone could help me build the query using the appropriate Aggregate functions, it would be MUCH appreciated.
What I need to return is all chemicals (ID) that DO NOT have an expiration date > Today + 30 for that specific ID.
For this question, you can use a HAVING clause. No WHERE is needed:
SELECT COUNT(*) as Count_ID, cr.[Chemical_ID]
FROM RDB.Chemical_Record cr
GROUP BY cr.[Chemical_ID]
HAVING MAX(cr.Expires_Date) <= DATEADD(day, 30, GETDATE())
ORDER BY cr.[Chemical_ID]
Using the HAVING MAX solved my problem and I was then able to work out exactly what I needed. I had to do some more research to figure out how to bring all my columns back, but that wasn't as difficult.
Here is my final solution:
WITH CHEM AS (
SELECT RDB.Chemical_Record.[Chemical_ID]
FROM RDB.Chemical_Record
GROUP BY RDB.Chemical_Record.[Chemical_ID]
HAVING MAX(RDB.Chemical_Record.Expires_Date) <= DATEADD(day, 60, GETDATE())
)
SELECT DISTINCT
RDB.Chemical_Record.[Chemical_ID],
RDB.Chemical_Record.[Expires_Date],
RDB.Assay_Group.[Assay_Group_Name] AS [Assay Group],
RDB.Chemical.[Chemical_Name],
RDB.Chemical.[Product_Number],
RDB.Chemical_Record.[Lot_Number],
RDB.Storage_Location.[Location_Name]
FROM RDB.Chemical_Record
INNER JOIN CHEM ON CHEM.Chemical_ID = RDB.Chemical_Record.Chemical_ID
LEFT JOIN RDB.Chemical ON Chemical_Record.[Chemical_ID] = Chemical.[ID_Chemical]
LEFT JOIN RDB.Storage_Location ON Storage_Location.[ID_Storage_Location] = Chemical_Record.[Storage_Location_ID]
LEFT JOIN RDB.Chemical_To_AGroup ON Chemical_To_AGroup.[Chemical_ID] = Chemical_Record.[Chemical_ID]
LEFT JOIN RDB.Assay_Group ON Assay_Group.[ID_Assay_Group] = Chemical_To_AGroup.[Assay_Group_ID]
WHERE Expires_Date >= DATEADD(day, -60, GETDATE())
ORDER BY RDB.Chemical_Record.[Chemical_ID], RDB.Chemical_Record.Expires_Date
And a screenshot showing the resulting search:

I am stuck on getting a previous value

I have been working on this SQL code for a bit and I cannot get it to display like I want. I have an operation that we send parts outside of our business but there is no time stamp on when that operation sent out.
I am taking the previous operation's last labor date and the purchase order creation date to try and find out how long it takes that department to issued a purchase order.
I have tried LAST_Value to add to my query. I have even played with LAG and couldn't get a anything but errors.
SELECT
JobOpDtl.JobNum,
JobOpDtl.OprSeq,
JobOpDtl.OpDtlDesc,
LastValue.ClockInDate,
LastValue.LastValue
FROM Erp.JobOpDtl
LEFT OUTER JOIN Erp.LaborDtl ON
LaborDtl.JobNum = JobOpDtl.JobNum
and LaborDtl.OprSeq = JobOpDtl.OprSeq
LEFT OUTER JOIN (
Select
LaborDtl.JobNum,
LaborDtl.OprSeq,
MAX(LaborDtl.ClockInDate) as ClockInDate,
LAST_VALUE (LaborDtl.ClockInDate) OVER (PARTITION BY OprSeq ORDER BY JobNum) as LastValue
FROM Erp.LaborDtl
GROUP BY
LaborDtl.JobNum,
LaborDtl.OprSeq,
LaborDtl.ClockInDate
) as LastValue ON
JobOpDtl.JobNum = LastValue.JobNum
and JobOpDtl.OprSeq = LastValue.OprSeq
WHERE JobOpDtl.JobNum = 'PA8906'
GROUP BY
JobOpDtl.JobNum,
LastValue.OprSeq,
JobOpDtl.OpDtlDesc,
JobOpDtl.OprSeq,
LastValue.ClockInDate,
LastValue.LastValue
No errors, just not displaying how I am wanting it.
I would like it to display the OperSeq with the previous OperSeq last transaction date.
The basic function you want is LAG (as you suggested) but you need to wrap it in a COALESCE. Here is a sample code that illustrates the concept
SELECT * INTO #Jobs
FROM (VALUES ('P1','Step1', '2019-04-01'), ('P1','Step2', '2019-04-02')
, ('P1','Step3', '2019-04-03'), ('P1','Step4', NULL),
('P2','Step1', '2019-04-01'), ('P2','Step2', '2019-04-03')
, ('P2','Step3', '2019-04-06'), ('P2','Step4', NULL)
) as JobDet(JobNum, Descript, LastDate)
SELECT *
, COALESCE( LastDate, LAG(LastDate,1)
OVER(PARTITION BY JobNum
ORDER BY COALESCE(LastDate,GETDATE()))) as LastValue
FROM #Jobs
ORDER BY JobNum, Descript
DROP TABLE #Jobs
To apply it to your specific problem, I'd suggest using a COMMON TABLE EXPRESSION that replaces LastValue and using that instead of the raw table for your queries.
Your example picture doesn't match any tables you reference in your code (it would help us significantly if you included code that created temp tables matching those referenced in your code) so this is a guess, but it will be something like this:
;WITH cteJob as (
SELECT JobNum, OprSeq, OpDtlDesc, ClockInDate
, COALESCE( LastValue, LAG(LastValue,1)
OVER(PARTITION BY JobNum
ORDER BY COALESCE(LastValue,GETDATE()))) as LastValue
FROM Erp.JobOptDtl
) SELECT *
FROM cteJob as J
LEFT OUTER JOIN LaborDtl as L
on J.JobNum = JobNum
AND J.OprSeq = L.OprSeq
BTW, if you clean up your question to provide a better example of your data (i.e. SELECT INTO sttements like in the start of my answer that produce tables that correspond to the tables in your code instead of an image of an excel file) I might be able to get you closer to what you need, but hopefully this is enough to get you on the right track and it's the best I can do with what you've provided so far.

Refer to another table and return data adjacent to Max() result

I have the following two tables:
Using SQL Server 2012, I want to know the INTERVAL from the Hourly table where the MaxWaitTime and Split match what comes from the Daily table for each day. I am assuming I need to use a window function here, but I can't figure out the right answer.
There may be times where MaxWaitTime is 0 for an entire day, and thus all rows from the hourly table match. In this scenario, I would prefer a Null answer, but the earliest INTERVAL for that day would be fine.
There will also be times where multiple INTERVALs have the same wait time. In this scenario the first INTERVAL where the MaxWaitTime is present that day should be returned.
You can use outer apply if you want at most one match:
Looks like a simple left join should work between the tables. I'm simply going by the data shown above...
The query should look something like this. If the join fails, then a NULL will be returned. Give it a go..
select d.*, h.interval as maxinterval
from daily d outer apply
(select top 1 h.*
from hourly h
where convert(date, h.interval) = d.row_date and
h.split = d.split and
h.maxwaittime = d.maxwaittime
order by h.interval asc
) h;
If you want NULL for multiple matches, you can do something similar:
select d.*, h.interval as maxinterval
from daily d outer apply
(select top 1 h.callsoffered, h.split, max(h.interval) as maxinterval
from hourly h
where convert(date, h.interval) = d.row_date and
h.split = d.split and
h.maxwaittime = d.maxwaittime
group by h.maxwaittime, h.split
having count(*) = 1
) h;
Looks like a simple left join should work between the tables. I'm simply going by the data shown above...
The query should look something like this. If the join fails, then a NULL will be returned. Give it a go..
select daily.* ,hourly.callsoffered, hourly.interval as maxinterval
from daily
left join hourly
on convert(date,hourly.interval) = daily.row_date
and hourly.split = daily.split
and hourly.maxwaittime = daily.maxwaittime

Datediff and aggregate

I am new to SQL so please excuse my lack of knowledge. This is the table i have based on the following statement:
'select S_OPERATION.OPERATIONID, CHANGE_H.SERVICEREQNO, CHANGE_H.UPDATEDDATE
from sunrise.S_OPERATION inner join
CHANGE_H on S_OPERATION.OPERATIONID = CHANGE_H.OPERATIONID
where (S_OPERATION.OPERATIONID = 102005212) OR
(S_OPERATION.OPERATIONID = 102005218) or
(s_operation.operationid = 102005406) or
(s_operation.operationid = 102005401) or
(s_operation.operationid = 102005215)'
enter image description here
I would like to be able to calculate the time difference between events within the same job.
Please note: OperationID=event, Servicereqno=job
My end goal is to calculate the average time taken between each event and export this into a report, but i am having problems getting past the first hurdle.
I have tried the following statement however it does not work:
WITH cteOps AS
(
SELECT
row_number() OVER (PARTITION BY change.servicereqid ORDER BY change.updateddate) seqid,
updateddate,
servicereqid
FROM CHANGE.updateddate, CHANGE.addedby, S_OPERATION.operationid, CHANGE.servicereqid
)
SELECT
DATEDIFF(millisecond, o1.updateddate, o2.updateddate) updateddatediff,
servicereqid
FROM cteOps o1
JOIN cteOps o2 ON o1.seqid=o2.seqid+1 AND o1.servicereqid=o2.servicereqid;
Many thanks in advance.
Your two queries look quite different having different table names, etc. So you'd probably have to adjust my query below to match what you actually have.
You can look into the previous record with LAG. So a query showing all those events with a time difference to the previous one could be:
select
c.updateddate
, c.addedby
, so.operationid
, c.servicereqid
, so.updateddate
, datediff
( millisecond
, lag(so.updateddate) over (partition by c.servicereqid order by so.updateddate)
, so.updateddate
) as updateddatediff
from change c
inner join change_h ch
on c.servicereqid = ch.servicereqno
and ch.operationid in (102005212, 102005218, 102005406, 102005401, 102005215)
inner join s_operation so
on ch.operationid = so.operationid
order by
c.servicereqid,
so.updateddate;
You can build up on this by using it as a derived table (a subquery in a FROM clause).

SQl Query get data very slow from different tables

I am writing a sql query to get data from different tables but it is getting data from different tables very slowly.
Approximately above 2 minutes to complete.
What i am doing is here :
1. I am getting data differences and on behalf of date difference i am getting account numbers
2. I am comparing tables to get exact data i need.
here is my query
select T.accountno,
MAX(T.datetxn) as MxDt,
datediff(MM,MAX(T.datetxn), '2011-6-30') as Diffs,
max(P.Name) as POName
from Account_skd A,
AccountTxn_skd T,
POName P
where A.AccountNo = T.AccountNo and
GPOCode = A.OfficeCode and
Code = A.POCode and
A.servicecode = T.ServiceCode
group by T.AccountNo
order by len(T.AccountNo) DESC
please help that how i can use joins or any other way to get data within very less time say 5-10 seconds.
Since it appears you are getting EVERY ACCOUNT, and performance is slow, I would try by creating a prequery by just account, then do a single join to the other join tables something like..
select
T.Accountno,
T.MxDt,
datediff(MM, T.MxDt, '2011-6-30') as Diffs,
P.Name as POName
from
( select T1.AccountNo,
Max( T1.DateTxn ) MxDt
from AccontTxn_skd T1
group by T1.AccountNo ) T
JOIN Account_skd A
on T.AccountNo = A.AccountNo
JOIN POName P
on A.POCode = P.Code <-- GUESSING as you didn't qualify alias.field
AND A.OfficeCode = P.GPOCode <-- in your query for these two fields
order by
len(T.AccountNo) DESC
You had other elements based on the T.ServiceCode matching, but since you are only grouping on the account number anyhow, did it matter which service code was used? Otherwise, you would need to group by both the account AND service code (which I would have added the service code into the prequery and added as join condition to the account table too).