PIVOT'ing in SQL server - sql

I have the below query whcih I want to pivot.
SELECT
tbl_track_empHours.track_empHours_hours as emphours
,tbl_track_empHours.track_empHours_date as empHDate
, tbl_track_jobInfo.track_jobInfo_jobNum AS JobNum
, tbl_track_jobInfo.track_jobInfo_ProjName AS ProjName
, tbl_track_jobCodes.track_jobCode_jc AS jc
, tbl_track_jobCodes.track_jobCode_id_pk AS ts_JobCodeID
, tbl_track_empHours.track_empHours_main_usr_id_fk
, tbl_track_jobInfo.track_jobInfo_id_pk AS ts_JobID
FROM tbl_track_empHours INNER JOIN
tbl_track_jobInfo ON tbl_track_empHours.track_empHours_jobinfo_id_fk=tbl_track_jobInfo.track_jobInfo_id_pk INNER JOIN
tbl_track_jobCodes ON tbl_track_empHours.track_empHours_jobCode_id_fk = tbl_track_jobCodes.track_jobCode_id_pk
WHERE (tbl_track_empHours.track_empHours_main_usr_id_fk = '268')
AND (tbl_track_empHours.track_empHours_date BETWEEN '05/09/2011' AND '05/15/2011')
ORDER BY tbl_track_jobInfo.track_jobInfo_jobNum, tbl_track_jobCodes.track_jobCode_jc!
The result looks like this.
I want to pivot the column 'emphours' against the rest of the columns. The pivoted columns should have the dates between '05/09/2011' AND '05/15/2011'
Any help appreciated.
Pivot result

This could help you for sure.
Select * from (Select JobNum,ProjName,jc,ts_JobCodeID,mainUsrFk,ts_JobID,
[05/09/2011] as col1,[05/11/2011] as col2,[05/12/2011] as col3,
[05/13/2011] as col4,[05/14/2011] as col5,[05/15/2011] as col6,[05/10/2011] as col7 from (
SELECT
tbl_track_empHours.track_empHours_hours
,tbl_track_empHours.track_empHours_date
, tbl_track_jobInfo.track_jobInfo_jobNum AS JobNum
, tbl_track_jobInfo.track_jobInfo_ProjName AS ProjName
, tbl_track_jobCodes.track_jobCode_jc AS jc
, tbl_track_jobCodes.track_jobCode_id_pk AS ts_JobCodeID
, tbl_track_empHours.track_empHours_main_usr_id_fk as mainUsrFk
, tbl_track_jobInfo.track_jobInfo_id_pk AS ts_JobID
FROM tbl_track_empHours INNER JOIN
tbl_track_jobInfo ON tbl_track_empHours.track_empHours_jobinfo_id_fk = tbl_track_jobInfo.track_jobInfo_id_pk INNER JOIN
tbl_track_jobCodes ON tbl_track_empHours.track_empHours_jobCode_id_fk = tbl_track_jobCodes.track_jobCode_id_pk
WHERE (tbl_track_empHours.track_empHours_main_usr_id_fk = '268')
AND (tbl_track_empHours.track_empHours_date BETWEEN '5/09/2011' AND '5/15/2011')
) o
PIVOT( SUM(o.track_empHours_hours)
FOR o.track_empHours_date in ([05/09/2011],[05/10/2011],[05/11/2011],[05/12/2011],
[05/13/2011],[05/14/2011],[05/15/2011]))p ) as a

Related

Which query is faster to execute

Following are two options to query CTE and NFSE data. Pls advise !
A similar approach may have to be used in many places.
I would like you to verify them and suggest, if there are better options.
Option 1: Query CTE with all necessary joins UNION with query on NFSe with all necessary joins
SELECT DISTINCT 'CTE' as docTypeID
, cte.isqn_mstr_cd as ctePk
, cte.ct_e_cd
, cter.stat_desc
, awb.CREATE_DT
, awb.AWB_NBR
, awb.SHPR_NM
, awbs.DEST_LOC_CD
, nfe.NT_FSCL_CD
, nfe.FSCL_DOC_NBR
FROM cte_identity_master cte
INNER JOIN cte_response_detail cter ON (cte.isqn_mstr_cd = cter.isqn_mstr_cd)
LEFT JOIN match_ref_awb mawb ON (cte.isqn_ref_cd = mawb.isqn_mstr_cd)
LEFT JOIN awb_cust_master awb ON (mawb.awb_nbr = awb.awb_nbr)
LEFT JOIN awb_shipment_detail awbs ON (awb.awb_nbr = awbs.awb_nbr)
LEFT JOIN match_ref_nfe mnfe ON (cte.isqn_ref_cd = mnfe.isqn_mstr_cd)
LEFT JOIN nfe_identity_master nfe ON (mnfe.nt_fscl_cd = nfe.nt_fscl_cd)
UNION
SELECT DISTINCT 'NFSE' as docTypeID
, nfse.isqn_mstr_cd as nfsePk
, nfse.rp_s_id
, nfser.stat_desc
, awb.CREATE_DT
, awb.AWB_NBR
, awb.SHPR_NM
, awbs.DEST_LOC_CD
, nfe.NT_FSCL_CD
, nfe.FSCL_DOC_NBR
FROM nfse_request_detail nfse
INNER JOIN nfse_response_detail nfser ON (nfse.isqn_mstr_cd = nfser.isqn_mstr_cd)
LEFT JOIN match_ref_awb mawb ON (nfse.isqn_ref_cd = mawb.isqn_mstr_cd)
LEFT JOIN awb_cust_master awb ON (mawb.awb_nbr = awb.awb_nbr)
LEFT JOIN awb_shipment_detail awbs ON (awb.awb_nbr = awbs.awb_nbr)
LEFT JOIN match_ref_nfe mnfe ON (nfse.isqn_ref_cd = mnfe.isqn_mstr_cd)
LEFT JOIN nfe_identity_master nfe ON (mnfe.nt_fscl_cd = nfe.nt_fscl_cd)
;
Option 2: Use Union of CTe and NFSe first and then apply joins with other tables
SELECT ctnf.*
, awb.CREATE_DT
, awb.AWB_NBR
, awb.SHPR_NM
, awbs.DEST_LOC_CD
, nfe.NT_FSCL_CD
, nfe.FSCL_DOC_NBR
FROM (
SELECT DISTINCT 'CTE' as docTypeID
, cte.isqn_mstr_cd as docPk
, cte.ct_e_cd as docNbr
, cter.stat_desc as docStat
, cte.isqn_ref_cd as matchRef
FROM cte_identity_master cte
INNER JOIN cte_response_detail cter ON (cte.isqn_mstr_cd = cter.isqn_mstr_cd)
UNION
SELECT DISTINCT 'NFSE' as docTypeID
, nfse.isqn_mstr_cd as nfsePk
, nfse.rp_s_id
, nfser.stat_desc
, nfse.isqn_ref_cd
FROM nfse_request_detail nfse
INNER JOIN nfse_response_detail nfser ON (nfse.isqn_mstr_cd = nfser.isqn_mstr_cd)
) ctnf
LEFT JOIN match_ref_awb mawb ON (ctnf.matchRef = mawb.isqn_mstr_cd)
LEFT JOIN awb_cust_master awb ON (mawb.awb_nbr = awb.awb_nbr)
LEFT JOIN awb_shipment_detail awbs ON (awb.awb_nbr = awbs.awb_nbr)
LEFT JOIN match_ref_nfe mnfe ON (ctnf.matchRef = mnfe.isqn_mstr_cd)
LEFT JOIN nfe_identity_master nfe ON (mnfe.nt_fscl_cd = nfe.nt_fscl_cd)
;
Both approaches of the above will have following Where Clause:
WHERE lower(cte.sttn_cd) = lower(:stationId)
and (:documentType is null or lower(:documentType) = 'cte')
and (:shipperName is null or lower(awb.shipperNm) like lower(concat(concat('%',:shipperName),'%')))
and (:awbCreated is null or to_char(awb.createDt, 'MM-DD-YYYY') = :awbCreated)
and (:awbNumber is null or m2.awbNbr like concat(concat('%',:awbNumber),'%'))
and (:serviceType = 0 or awbs.baseServiceCd = :serviceType)
and (:commitmentDate is null or awbs.commitmentDate = :commitmentDate)
and (:ursa is null or lower(awbs.ursaCd) like lower(concat(concat('%',:ursa),'%')))
and (:destLocationId is null or lower(awbs.destLocCd) like lower(concat(concat('%',:destLocationId),'%')))
and (:nfeNumber is null or nfe.fiscalDocumentNumber like concat(concat('%',:nfeNumber),'%'))
PLEASE SUGGEST - Output of these two approaches to get data which one will be better to fix at Java End to retrieve the data.
Any help will be greatly appreciated. Also suggest if there is any other better query apart from these two!

SQL Select multiple joins and MAX(field) result

I'm using IBM Cognos to create a report which allows for fairly standard SQL. I am ultimately trying to take data from 2 tables and compare them to each other to ensure they match. Billing_Term, Bill_Period and Contract_Term_Amount all need to match when comparing a given Contract_Number, Contract_Item and Stream_Type between t1 and t3 but only for the MAX Seq_No from t3.
I tried a simple MAX() on Seq_No but that didn't work so I'm looking for help in limiting the results to the MAX Seq_No for the associated query results.
SELECT
t1.Contract_Number,
t1.Contract_Item,
t1.Stream_Type,
t1.Billing_Term,
t1.Bill_Period,
t1.Contract_Term_Amount,
t2.Reference_Document,
t3.Billing_Term,
t3.Bill_Period,
t3.Contract_Term_Amount,
t3.Seq_No
FROM
LeasingStreamData t1
INNER JOIN ContractsData t2 ON t1.Contract_Number = t2.Sales_Document
LEFT JOIN LeasingStreamData t3 ON t2.Reference_Document = t3.Contract_Number AND
t1.Contract_Item = t3.Contract_Item AND
t1.Stream_Type = t3.Stream_Type
WHERE
t1.Contract_Number IN ([some list of contracts])
GROUP BY
t1.Contract_Number,
t1.Contract_Item,
t1.Stream_Type,
t1.Billing_Term,
t1.Bill_Period,
t1.Contract_Term_Amount,
t2.Reference_Document,
t3.Billing_Term,
t3.Bill_Period,
t3.Contract_Term_Amount,
t3.Seq_No
I hope this is enough to get some much needed help, many thanks for any assistance you can provide!
If I understand you requirement, I think you want to create queries and join them in a way that will look like this SQL:
SELECT
t1.Contract_Number
, t1.Contract_Item
, t1.Stream_Type
, t1.Billing_Term
, t1.Bill_Period
, t1.Contract_Term_Amount
, t2.Reference_Document
, t3.Billing_Term
, t3.Bill_Period
, t3.Contract_Term_Amount
, t3.Seq_No
FROM (
SELECT Contract_Number
, Contract_Item
, Stream_Type
, Billing_Term
, Bill_Period
, Contract_Term_Amount
FROM LeasingStreamData
WHERE Contract_Number in ([some list of contracts])
) t1
INNER JOIN (
SELECT Sales_Document
, Reference_Document
FROM ContractsData
WHERE Sales_Document in ([some list of contracts])
) t2 ON t1.Contract_Number = t2.Sales_Document
INNER JOIN LeasingStreamData t3 ON t2.Reference_Document = t3.Contract_Number
AND t1.Contract_Item = t3.Contract_Item
AND t1.Stream_Type = t3.Stream_Type
INNER JOIN (
select max(Seq_No) as Seq_No
, Contract_Number
, Contract_Item
, Stream_Type
from LeasingStreamData lsd
group by Contract_Number
, Contract_Item
, Stream_Type
) maxseq on maxseq.Contract_Number = t3.Contract_Number
and maxseq.Contract Item = t3.Contract_Item
and maxseq.Stream_Type = t3.Stream_Type
and maxseq.Seq_No = t3.Seq_No
WHERE t1.Billing_Term <> t3.Billing_Term
and t1.Bill_Period <> t3.Bill_Period
and t1.Contract_Term_Amount <> t3.Contract_Term_Amount
GROUP BY
t1.Contract_Number
, t1.Contract_Item
, t1.Stream_Type
, t1.Billing_Term
, t1.Bill_Period
, t1.Contract_Term_Amount
, t2.Reference_Document
, t3.Billing_Term
, t3.Bill_Period
, t3.Contract_Term_Amount
, t3.Seq_No
I think this will filter to only the max Seq_No for t3 and return only the records that you care about (the ones that don't match).
Try this:
SELECT t1.Contract_Number
,t1.Contract_Item
,t1.Stream_Type
,t1.Billing_Term
,t1.Bill_Period
,t1.Contract_Term_Amount
,t2.Reference_Document
,t3.Billing_Term
,t3.Bill_Period
,t3.Contract_Term_Amount
,t3.Seq_No
FROM LeasingStreamData t1
INNER JOIN ContractsData t2 ON t1.Contract_Number = t2.Sales_Document
LEFT JOIN (
SELECT Contract_Number
,Contract_Item
,Stream_type
,MAX(Seq_No) AS "Seq_No"
FROM LeasingStreamData
GROUP BY Contract_Number
,Contract_Item
,Stream_Type
) t3 ON t2.Reference_Document = t3.Contract_Number
AND t1.Contract_Item = t3.Contract_Item
AND t1.Stream_Type = t3.Stream_Type
WHERE t1.Contract_Number IN ([some list of contracts])
Since the rollup for the aggregate function (MAX) relies on the group by to determine context, you have to isolate it via a subquery to get the max before joining to the rest of the tables.
Also, since you are preaggregating the max sequence number, you no longer need a group by in the main query.

Convert / translate t-sql query to MS Access query

I have a SQL query that I want to use in MS Access, but I can't get it right. Any help would be apprecitated.
select tblKPIData.Id
, tblKPIData.KPI_id
, tblKPIData.Quantity
, tblKPIData.FinancialMonth
, tblKPIData.FinancialYear
, tblKPIData.ImportTimestamp
, tblDashboadKPI.Dashboard_Id
from (
select tblKPIData.kpi_id,
max(tblKPIData.ImportTimestamp) as ImportTimestamp
from tblKPIData
group by tblKPIData.KPI_id
)
as b
inner join tblKPIData
on tblKPIData.KPI_id = b.KPI_id
and tblKPIData.ImportTimestamp = b.ImportTimestamp
right join tblDashboadKPI
on tblDashboadKPI.KPI_Id = tblKPIData.KPI_id
where FinancialMonth = 'nov'
and FinancialYear = 2016
and tblDashboadKPI.Dashboard_Id = 5
order by tblKPIData.Id
,tblKPIData.KPI_id
If your query currently works, I would suggest:
select kp.Id, kp.KPI_id, kp.Quantity, kp.FinancialMonth,
kp.FinancialYear, kp.ImportTimestamp,
d.Dashboard_Id
from ((select tblKPIData.kpi_id,
max(tblKPIData.ImportTimestamp) as ImportTimestamp
from tblKPIData
group by tblKPIData.KPI_id
) as b inner join
tblKPIData as kp
on kp.KPI_id = b.KPI_id and kp.ImportTimestamp = b.ImportTimestamp
) right join
tblDashboadKPI as d
on d.KPI_Id = kp.KPI_id
where FinancialMonth = "nov" and FinancialYear = 2016 and
d.Dashboard_Id = 5
order by kp.Id, kp.KPI_id;
Changes:
JOINs need to have additional parentheses
Strings uses double quots
I introduced table aliases as well, to simplify the query
I think I have the solution:
SELECT tblKPIData.Id
, tblKPIData.KPI_id
, tblKPIData.Quantity
, tblKPIData.FinancialMonth
, tblKPIData.FinancialYear
, tblKPIData.ImportTimestamp
, tblKPIData.Type
, tblDashboadKPI.Dashboard_Id
FROM tblDashboadKPI
INNER JOIN tblKPIData
ON tblDashboadKPI.KPI_Id = tblKPIData.KPI_id
WHERE (((tblKPIData.FinancialMonth)="nov")
AND ((tblKPIData.FinancialYear)=2016)
AND ((tblKPIData.ImportTimestamp)=(select max(d2.ImportTimestamp)
from tblKPIData as d2
where d2.KPI_Id = tblKPIData.KPI_Id))
AND ((tblDashboadKPI.Dashboard_Id)=5));
Thanx for your help!

How do I change this sql statement to only select the first from each ID?

I have the below code to select from a database, however, I only want the first record for each unique ID. Is there a way to change the SQL to achieve this?
SELECT
[CARL_Property].ID
,[PrDoorNum]
,[PrAddress1]
,[PrAddress2]
,[PrAddress3]
,[PrAddress4]
,[PrPostcode]
,[PrRent]
,[PrAgreedRent]
,[PrCommence]
,[PrEnd]
,[PrAvailable]
,[PrGrossIncome]
,[PrCouncilTax]
,[PrInventoryFee]
,[PrLetFee]
,[PrReletFee]
,[PrDateWithdrawn]
,[Rent Review]
,CARL_Owners.OwForenames
,CARL_Owners.OwSurname
,CARL_Property_List.[ID]
,CARL_Property_List.[PrId]
,CARL_Property_List.[PLBedrooms]
,CARL_Property_List.[PlRooms]
,CARL_Property_List.[PlBathrooms]
,CARL_Property_List.[PlReceptions]
,CARL_Property_List.[PlDeposit]
,CARL_Tenant_Contacts.[Tenant Name]
,CARL_New_Tenants.[TnLeaseperiod]
,CARL_Property_List.[PlAdvertising]
,[CARL_Property_Memos].[PrNotes]
,[CARL_Safety].[PrGasInsp]
from dbo.CARL_Property Join dbo.[CARL_Property_Memos] on CARL_Property.ID=CARL_Property_Memos.PrID Join dbo.CARL_Owners on CARL_Owners.ID=CARL_Property.OwID Join dbo.CARL_PROPERTY_LIST ON dbo.CARL_PROPERTY.ID=dbo.CARL_PROPERTY_LIST.PrId Join dbo.[CARL_New_Tenants] ON CARL_New_Tenants.PrId=CARL_Property.ID JOIN CARL_Tenant_Contacts ON CARL_New_Tenants.ID = CARL_Tenant_Contacts.TnID Join [dbo].[CARL_Safety] On dbo.CARL_Property.ID=dbo.CARL_Safety.PrID
The result is as seen below.
Something along these lines I think is what you are looking for. Also, notice that I used aliases in your main query. It makes this a lot simpler to work with and reduces the amount of typing by a LOT.
with SortedResults as
(
SELECT
cp.ID
, ROW_NUMBER() over(partition by cp.ID order by pl.ID) as RowNum --order by whatever column defines "first"
, [PrDoorNum]
, [PrAddress1]
, [PrAddress2]
, [PrAddress3]
, [PrAddress4]
, [PrPostcode]
, [PrRent]
, [PrAgreedRent]
, [PrCommence]
, [PrEnd]
, [PrAvailable]
, [PrGrossIncome]
, [PrCouncilTax]
, [PrInventoryFee]
, [PrLetFee]
, [PrReletFee]
, [PrDateWithdrawn]
, [Rent Review]
, o.OwForenames
, o.OwSurname
, pl.[ID] as PL_ID
, pl.[PrId]
, pl.[PLBedrooms]
, pl.[PlRooms]
, pl.[PlBathrooms]
, pl.[PlReceptions]
, pl.[PlDeposit]
, tc.[Tenant Name]
, nt.[TnLeaseperiod]
, pl.[PlAdvertising]
, pm.[PrNotes]
, cs.[PrGasInsp]
from dbo.CARL_Property p
Join dbo.[CARL_Property_Memos] pm on p.ID = pm.PrID
Join dbo.CARL_Owners o on o.ID = p.OwID
Join dbo.CARL_PROPERTY_LIST pl ON p.ID = pl.PrId
Join dbo.[CARL_New_Tenants] nt ON nt.PrId = p.ID
JOIN CARL_Tenant_Contacts tc ON nt.ID = tc.TnID
Join [dbo].[CARL_Safety] cs On p.ID = cs.PrID
)
select *
from SortedResults
where RowNum = 1
order by ID

How to rewrite query

I need to update based on a select. The following errors with: the column '' was specified multiple times for Q
UPDATE Evolution1.DimAdministrator
SET Evolution1.DimAdministrator.ClaimSystemCodeId = 17
FROM Evolution1.DimAdministrator da INNER JOIN (
Select
ExtractId,
base.AdministratorId,
base.CardprocessorAdministratorId,
AdministratorName,
EffectiveDate,
CancelDate ,
State,
StageError ,
AdministratorKey,
CustomerKey ,
Name ,
EffectiveDateKey ,
CancelDateKey,
StateProvinceKey ,
Alias ,
NavId ,
warehouse.AdministratorId ,
warehouse.CardprocessorAdministratorId,
warehouse.ClaimSystemCodeId,
Inserted ,
Updated
FROM OneStage.OnePay.Administrator base
INNER JOIN OneWarehouse.Evolution1.DimAdministrator warehouse ON base.AdministratorId = warehouse.AdministratorId
WHERE base.ClaimSystemCodeId <> warehouse.ClaimSystemCodeId
AND base.ClaimSystemCodeId = 1
) AS Q
Help please. Thanks.
You have multiple columns with duplicate names.
Put an alias on them like this:
UPDATE Evolution1.DimAdministrator
SET Evolution1.DimAdministrator.ClaimSystemCodeId = 17
FROM Evolution1.DimAdministrator da INNER JOIN (
Select
ExtractId,
base.AdministratorId AS base_AdminID,
base.CardprocessorAdministratorId AS base_CardID,
AdministratorName,
EffectiveDate,
CancelDate ,
State,
StageError ,
AdministratorKey,
CustomerKey ,
Name ,
EffectiveDateKey ,
CancelDateKey,
StateProvinceKey ,
Alias ,
NavId ,
warehouse.AdministratorId wh_AdminID,
warehouse.CardprocessorAdministratorId AS WH_CardID,
warehouse.ClaimSystemCodeId,
Inserted ,
Updated
FROM OneStage.OnePay.Administrator base
INNER JOIN OneWarehouse.Evolution1.DimAdministrator warehouse ON base.AdministratorId = warehouse.AdministratorId
WHERE base.ClaimSystemCodeId <> warehouse.ClaimSystemCodeId
AND base.ClaimSystemCodeId = 1
) AS Q
Are you sure you don't need to JOIN Q ON something?