SQL Server query that contains a derived table - sql-server

I have created a select query that contains one regular table and two derived tables (subqueries). The derived tables are both joined with the regular table with left joins. The regular table contains over 7000 rows, but the query output is around 3000 rows. It has to be equal to the number of records in the regular table. What is my mistake?
SELECT T0.[ItemCode],
T0.[ItemName],
CASE T0.[PrcrmntMtd] WHEN 'B' THEN 'Inkoop' ELSE 'Productie' END AS Verwervingsmethode,
T0.[OnHand] AS Voorraad_excl_grondstof_reeds_verwerkt,
T1.[Reeds_geproduceerd] AS Grondstof_reeds_verwerkt,
CASE WHEN T1.[Reeds_geproduceerd] IS NULL
THEN T0.[OnHand]
ELSE T0.[OnHand]-T1.[Reeds_geproduceerd]
END AS Voorraad_incl_grondstof_reeds_verwerkt,
T2.[Nog_te_produceren] AS Geplande_productie_halffabrikaat_eindproduct,
T1.[Nog_te_produceren] AS Gereserveerd_voor_productie_grondstof_halffabrikaat,
CASE WHEN T1.[Reeds_geproduceerd] IS NULL
THEN (T0.[OnHand]/T2.[Nog_te_produceren])*30
ELSE ((T0.[OnHand]-T1.[Reeds_geproduceerd])/T2.[Nog_te_produceren])*30
END AS Dagen_voorraad_halffabrikaat_eindproduct,
CASE WHEN T1.[Reeds_geproduceerd] IS NULL
THEN (T0.[OnHand]/T1.[Nog_te_produceren])*30
ELSE ((T0.[OnHand]-T1.[Reeds_geproduceerd])/T1.[Nog_te_produceren])*30
END AS Dagen_voorraad_grondstof_halffabrikaat
FROM OITM T0
LEFT JOIN (
SELECT T1.[ItemCode],
SUM(T0.[PlannedQty]*T1.[BaseQty]) AS Geplande_productie,
CASE WHEN SUM(T0.CmpltQty) IS NULL THEN SUM(T0.[PlannedQty]*T1.[BaseQty]) ELSE SUM(T0. [CmpltQty]*T1.[BaseQty]) END AS Reeds_geproduceerd,
CASE WHEN SUM(T0.CmpltQty) IS NULL THEN SUM(T0.[PlannedQty]*T1.[BaseQty]) ELSE SUM(T0.[PlannedQty]*T1.[BaseQty])-SUM(T0.[CmpltQty]*T1.[BaseQty]) END AS Nog_te_produceren
FROM OWOR T0
INNER JOIN WOR1 T1 ON T0.DocEntry = T1.DocEntry
WHERE T0.DueDate <= getdate()+30
AND (T0.[Status] LIKE 'p'
OR T0.[Status] LIKE 'r')
GROUP BY T1.[ItemCode]
) AS T1
ON T0.ItemCode = T1.ItemCode
LEFT JOIN (
SELECT T0.[ItemCode],
SUM(T0.[PlannedQty]) AS Geplande_productie,
SUM(T0.[CmpltQty]) AS Reeds_geproduceerd,
SUM(T0.[PlannedQty])-SUM(T0.[CmpltQty]) AS Nog_te_produceren
FROM OWOR T0
INNER JOIN WOR1 T1 ON T0.DocEntry = T1.DocEntry
WHERE T0.DueDate <= getdate()+30
AND (T0.[Status] LIKE 'p'
OR T0.[Status] LIKE 'r')
GROUP BY T0.[ItemCode]
) AS T2
ON T0.ItemCode = T2.ItemCode
I mentioned all the where clauses. If I red the linked page correct, that cant be the problem.
I also changed the table names and column names of the derived tables. Now all table names and column names are unique.
But still the same problem. When i delete the last two case statements in select, i do get all the output lines, but i dont see any problems in these case statements.
SELECT T0.[ItemCode],
T0.[ItemName],
CASE T0.[PrcrmntMtd] WHEN 'B' THEN 'Inkoop' ELSE 'Productie' END AS Verwervingsmethode,
T0.[OnHand] AS Voorraad_excl_grondstof_reeds_verwerkt,
T3.[Reeds_geproduceerd_grond] AS Grondstof_reeds_verwerkt,
CASE WHEN T3.[Reeds_geproduceerd_grond] IS NULL
THEN T0.[OnHand]
ELSE T0.[OnHand]-T3.[Reeds_geproduceerd_grond]
END AS Voorraad_incl_grondstof_reeds_verwerkt,
T6.[Nog_te_produceren_eind] AS Geplande_productie_halffabrikaat_eindproduct,
T3.[Nog_te_produceren_grond] AS Gereserveerd_voor_productie_grondstof_halffabrikaat,
CASE WHEN T3.[Reeds_geproduceerd_grond] IS NULL
THEN 30*(T0.[OnHand]/T6.[Nog_te_produceren_eind])
ELSE 30*((T0.[OnHand]-T3.[Reeds_geproduceerd_grond])/T6.[Nog_te_produceren_eind])
END AS Dagen_voorraad_halffabrikaat_eindproduct,
CASE WHEN T3.[Reeds_geproduceerd_grond] IS NULL
THEN 30*(T0.[OnHand]/T3.[Nog_te_produceren_grond])
ELSE 30*((T0.[OnHand]-T3.[Reeds_geproduceerd_grond])/T3.[Nog_te_produceren_grond])
END AS Dagen_voorraad_grondstof_halffabrikaat
FROM OITM T0
LEFT JOIN (
SELECT T2.[ItemCode] AS ItemCode_grond,
SUM(T1.[PlannedQty]*T2.[BaseQty]) AS Geplande_productie_grond,
CASE WHEN SUM(T1.CmpltQty) IS NULL
THEN SUM(T1.[PlannedQty]*T2.[BaseQty])
ELSE SUM(T1.[CmpltQty]*T2.[BaseQty])
END AS Reeds_geproduceerd_grond,
CASE WHEN SUM(T1.CmpltQty) IS NULL
THEN SUM(T1.[PlannedQty]*T2.[BaseQty])
ELSE SUM(T1.[PlannedQty]*T2.[BaseQty])-SUM(T1.[CmpltQty]*T2.[BaseQty])
END AS Nog_te_produceren_grond
FROM OWOR T1
INNER JOIN WOR1 T2 ON T1.DocEntry = T2.DocEntry
WHERE T1.DueDate <= getdate()+30
AND (T1.[Status] LIKE 'p'
OR T1.[Status] LIKE 'r')
GROUP BY T2.[ItemCode]
) AS T3
ON T0.ItemCode = T3.ItemCode_grond
LEFT JOIN (
SELECT T4.[ItemCode] AS ItemCode_eind,
SUM(T4.[PlannedQty]) AS Geplande_productie_eind,
SUM(T4.[CmpltQty]) AS Reeds_geproduceerd_eind,
SUM(T4.[PlannedQty])-SUM(T4.[CmpltQty]) AS Nog_te_produceren_eind
FROM OWOR T4
INNER JOIN WOR1 T5 ON T4.DocEntry = T5.DocEntry
WHERE T4.DueDate <= getdate()+30
AND (T4.[Status] LIKE 'p'
OR T4.[Status] LIKE 'r')
GROUP BY T4.[ItemCode]
) AS T6
ON T0.ItemCode = T6.ItemCode_eind

Related

SQL Case Statement with SELECT inside INNER JOIN. Error of multi-part could not be bound

I am writing an INNER JOIN that added fields like CompanyId etc..
But in my CASE inside the INNER JOIN I am getting an error after the WHERE
The error say on the IR.MyId and ICB1.MyId
"multi-part identifier could not be bound"
My intention for this query is to add a CASE inside the INNER JOIN.
So the first column is A.CompanyId. The second column will be the CASE statement to check if the ID exists in another table. If not, it will do another SELECT statement, ELSE just MyID.
But I get an error on the SELECT COUNT(*) inside the CASE WHEN.
Any help is appreciated. Thanks.
INNER JOIN
(SELECT DISTINCT
A.CompanyId,
CASE
WHEN (SELECT count(*)
FROM Table1 IBC1
WHERE IR.MyId = ICB1.MyId) == 0
THEN 1
ELSE 0
END
FROM
cmp.CompanyNews A) E ON NP.CompanyId = E.CompanyId
I don't have your full query, but if it's viable I'd take the following approach to this:
...
CASE
WHEN ICB1_ID.ID IS NULL
THEN 1
ELSE 0
END [ColumnName]
FROM
...
INNER JOIN
(
SELECT DISTINCT A.CompanyId
FROM cmp.CompanyNews A
) E
ON NP.CompanyId = E.CompanyId
OUTER APPLY
(
SELECT TOP 1 ICB1.MyID ID
FROM Table1 IBC1
WHERE ICB1.MyId = IR.MyId
) ICB1_ID

Select Case determines Exit code or run Update statement

Trying to get the select case statement to control whether nothing happens or a table is updated based on the sum of three fields from two different tables. One of the tables is a temp table (#tempGLsum). This holds the id field and the sum amount. The "amt" field in the tblPcardGL table should never go below 0 (zero). If it would, then the flow should stop. If it will still be > 0, then the next block of code would run, which updates the tblPcardGL table.
Any assistance would be appriciated!
Thanks
declare #glID int
create table #tempGLsum
(glID int, sumAmt decimal(18,2))
insert into #tempGLsum
(glID, sumAmt)
select tblPcardReclass.glID,
sum(tblPcardReclass.reclassAmt)
from tblPcardReclass
where tblPcardReclass.glID = #glID
group by tblPcardReclass.glID
select
case when (tblPcardGL.orgAmt - tblPcardGL.amt - #tempGLsum.sumAmt) < 0
then 'stop here and let the user know it's below zero'
else
'run the code_below'
end
from tblPcardGL
left outer join #tempGLsum ON
tblPcardGL.glID = #tempGLsum.glID
where tblPcardGL.glID = #glID
-- code_below
update tblPcardGL
set amt =
(
select
case (select COUNT(*) as numRecs from #tempGLsum)
when 0 then
tblPcardGL.orgAmt
else
(tblPcardGL.orgAmt - #tempGLsum.sumAmt)
end
)
from tblPcardGL
left outer join #tempGLsum ON
tblPcardGL.glID = #tempGLsum.glID
where tblPcardGL.glID = #glID
You can't really do what you want with a case statement. You just have to do it in two steps:
First run the select with a where clause to show the user all the problems:
select tblPcardGL.*, 'Below Zero!' Error
from tblPcardGL
left outer join #tempGLsum ON
tblPcardGL.glID = #tempGLsum.glID
where tblPcardGL.glID = #glID
and (tblPcardGL.orgAmt - tblPcardGL.amt - #tempGLsum.sumAmt) < 0
Then do the update with another where clause:
update tblPcardGL
set amt =
(
select
case (select COUNT(*) as numRecs from #tempGLsum)
when 0 then
tblPcardGL.orgAmt
else
(tblPcardGL.orgAmt - #tempGLsum.sumAmt)
end
)
from tblPcardGL
left outer join #tempGLsum ON
tblPcardGL.glID = #tempGLsum.glID
where tblPcardGL.glID = #glID
and (tblPcardGL.orgAmt - tblPcardGL.amt - #tempGLsum.sumAmt) >= 0
You should consider wrapping all your #tempGLsum.sumAmt fields in isnull(#tempGLsum.sumAmt,0) because you used a left join so that column might evaluate to null, which will make any expression it is in become null.

Data result should appear on one column

I am a self learner in SQL; I have created this code:
SELECT T0.[CardName], T0.[DocDate], T0.[DocDueDate], T2.[U_ExpDelDate], T0.[DocStatus], T1.[SlpName],
CASE
WHEN DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) <= 0 THEN 'Delivered'
WHEN DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) >= 0 THEN 'Please Check'
ELSE NULL END AS 'Status',
DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) AS 'Age'
FROM OPOR T0 INNER JOIN OSLP T1 ON T0.[SlpCode] = T1.[SlpCode] INNER JOIN POR1 T2 ON T0.[DocEntry] = T2.[DocEntry]
WHERE T0.[DocStatus] ='O' and T2.[U_ExpDelDate] is not null
I am getting the right result, but now I wanted Join the result Delivered and Please Check in Age column.
Do you have any idea?
Concatenating strings in sql server is done by either using the + operator or the CONCAT method.
Try this:
SELECT T0.[CardName], T0.[DocDate], T0.[DocDueDate], T2.[U_ExpDelDate], T0.[DocStatus], T1.[SlpName],
CASE
WHEN DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) <= 0 THEN 'Delivered '
WHEN DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) > 0 THEN 'Please Check ' + CAST(DATEDIFF(day,DocDueDate,T2.[U_ExpDelDate]) as varchar)
END AS 'Age'
FROM OPOR T0 INNER JOIN OSLP T1 ON T0.[SlpCode] = T1.[SlpCode] INNER JOIN POR1 T2 ON T0.[DocEntry] = T2.[DocEntry]
WHERE T0.[DocStatus] ='O' and T2.[U_ExpDelDate] is not null
I've removed the else part since it's never going there, the datediff function will either return a value that is less than or equal to 0 or more than 0.

case statement to select multiple rows at once

I am looking to pull the same columns from two different tables, based on a conditional argument.
So i have stumbled upon the CASE statement which I have not used much before. I have found this will work for me in this mannor, but I would like it if I could do one CASE statement and then select the columns i need, rather then doing it per column.
Here is an example of what I have and working, just seems a little redundant.
SELECT TOP(10)
u1.userid as userid,
version = CASE
WHEN (u2.userid IS NULL OR u1.enabled = 0)
THEN 3
ELSE 4
END,
nameOrg = CASE
WHEN (u2.userid IS NULL OR u1.enabled = 0)
THEN CONVERT(NVARCHAR, u1.title)
ELSE CONVERT(NVARCHAR, u2.title)
END,
nameContact = CASE
WHEN (u2.userid IS NULL OR u1.enabled = 0)
THEN CONVERT(NVARCHAR, u1.contact)
ELSE CONVERT(NVARCHAR, u2.contact)
END,
pltName = CASE
WHEN (u2.userid IS NULL OR u1.enabled = 0)
THEN p1.name
ELSE p2.name
END
FROM
usr1 u1
LEFT OUTER JOIN
usr2 u2
ON u1.userid = u2.userid
LEFT OUTER JOIN
plt2 p2
ON u2.pltid = p2.pltid
LEFT OUTER JOIN
plt1 p1
ON u1.pltid = p1.pltid
Any advise?
Edit mov 7, 5:22: added join to plt table and pltName case, to add to required functionality.
In the case that there is no matching userid in the usr2 dataset, all the fields will be null. You could use the isnull function to make it a little less verbose as I have done below, but you won't get down to a single line.
SELECT TOP(10)
u1.userid as userid
,version = CASE
WHEN (u2.userid IS NULL OR u1.enabled = 0)
THEN 3
ELSE 4
END
,CONVERT(NVARCHAR,isnull(u2.title,u1.title)) nameOrg
,CONVERT(NVARCHAR,isnull(u2.contact,u1.contact)) nameContact
FROM
usr1 u1
LEFT OUTER JOIN
usr2 u2
ON u1.userid = u2.userid

Joining two queries horizontally

I wrote two queries below that produce one row of data each.
What is the best way to combine them such that I am LEFT with only a single row of data?
These are coming FROM two DISTINCT databases named : [ASN01] and [dsi_ASN_dsicx]
I have 70 pairs of databases like this but am showing only one for simplicity.
The fact that the three letter acronym ASN is common to both database names is no mistake and if needed can be a part of the solution.
Current Results:
Site, Elligence (header)
ASN, 100.00
Site, GP_Total (header)
ASN, 120.00
Desired results:
Site, GP_Total, Elligence (header)
ASN, 120.00, 100.00
SELECT 'ASN' AS Site ,
CASE SUM(perdblnc)
WHEN NULL THEN 0
ELSE -1 * SUM(PERDBLNC)
END AS GP_Total
FROM [ASN01].[dbo].[GL10110] T1
LEFT OUTER JOIN [ASN01].[dbo].[GL00105] T2 ON [T1].[ACTINDX] = [T2].[ACTINDX]
WHERE YEAR1 = 2012
AND PERIODID IN ( '2' )
AND ACTNUMST IN ( '4200-0000-C', '6940-0000-C', '6945-0000-C',
'6950-0000-C' )
SELECT 'ASN' AS [Site] ,
SUM(pi.amount) AS [Elligence]
FROM [dsi_ASN_dsicx].dbo.charge c
LEFT JOIN [dsi_ASN_dsicx].dbo.paymentitem pi ON c.idcharge = pi.chargeid
LEFT JOIN [dsi_ASN_dsicx].dbo.payment p ON pi.paymentid = p.idpayment
LEFT JOIN [dsi_ASN_dsicx].dbo.paymenttype pt ON p.paymenttypeid = pt.idpaymenttype
WHERE pi.amount != 0
AND pt.paymentmethod NOT IN ( '5', '7' )
AND pt.paymentmethod IS NOT NULL
AND p.sdate >= '20120201'
AND p.sdate <= '20120229'
WIthout going through and changing any of your queries, the easiest way would be to use temp tables using the "WITH" common_table_expression. Table1 and Table2 are temp tables created from your select statements. Therefore, we select table1 and join table2.
Let me know if there are any syntax problems, I don't have anything to test this on presently.
;With Table1 as (SELECT 'ASN' as Site, Case sum(perdblnc)
WHEN NULL THEN 0
ELSE -1*sum(PERDBLNC) END as GP_Total
FROM [ASN01].[dbo].[GL10110] T1
Left Outer Join [ASN01].[dbo].[GL00105] T2
ON [T1]. [ACTINDX]= [T2]. [ACTINDX]
WHERE YEAR1 = 2012
AND PERIODID in ('2')
AND ACTNUMST in ('4200-0000-C', '6940-0000-C', '6945-0000-C', '6950-0000-C'))
, Table2 as (SELECT
'ASN' as [Site],
SUM(pi.amount) as [Elligence]
FROM [dsi_ASN_dsicx].dbo.charge c
LEFT JOIN [dsi_ASN_dsicx].dbo.paymentitem pi on c.idcharge = pi.chargeid
LEFT JOIN [dsi_ASN_dsicx].dbo.payment p on pi.paymentid = p.idpayment
LEFT JOIN [dsi_ASN_dsicx].dbo.paymenttype pt on p.paymenttypeid = pt.idpaymenttype
WHERE pi.amount != 0
AND pt.paymentmethod not in ('5','7')
AND pt.paymentmethod is not null
AND p.sdate >='20120201' and p.sdate <= '20120229')
SELECT * FROM Table1
LEFT JOIN Table2 ON Table1.site = Table2.site
Hope this helps! Marks as answer if it is =)

Resources