Get value from a joined table with no value in primary table - sql

The query shown below is just about right, but I need to have a row for each fiscal Id, i.e. in the output shown below, there needs to be a new row after row 4 with data (screen shot below)
The query I'm using is:
SELECT a.companyId,a.profitCenterID,a.coaID,a.fiscalId,
COALESCE(SUM(a.amount * -1),0) amount,
twelveMo = (
SELECT COALESCE(SUM(amount * -1), 0)
FROM gl a1
LEFT OUTER JOIN fiscal f ON a1.fiscalId=f.Id
WHERE
a1.companyId = a.companyId AND
a1.profitCenterId = a.profitCenterId AND
a1.coaId = a.coaId AND
f.Id > a.fiscalId - 12 AND
f.Id <= a.fiscalId
)
FROM gl a
INNER JOIN coa c ON c.Id=a.coaId AND c.statementType=4
GROUP BY companyId,profitCenterId,coaId,a.fiscalId
ORDER BY companyId,profitCenterId,coaId,a.fiscalId

I don't know your sample datas and your schema's, so I've just added my query on the top of your's.
;WITH CTE_NUM_TEMP AS
(
SELECT 1 AS Fiscal
UNION ALL
SELECT Fiscal+1 FROM CTE_NUM_TEMP
WHERE Fiscal+1<=100
)
SELECT ISNULL(Der.companyId,1) AS companyId,ISNULL(Der.profitCenterID,1) AS profitCenterID,
ISNULL(Der.coaID,40000) AS coaID,IIF(twelveMo IS NULL,LAG(twelveMo,1) OVER(ORDER BY Fiscal),twelveMo) AS twelveMo
FROM CTE_NUM_TEMP AS Num
LEFT JOIN
(
SELECT a.companyId,a.profitCenterID,a.coaID,a.fiscalId,
COALESCE(SUM(a.amount * -1),0) amount,
twelveMo = (
SELECT COALESCE(SUM(amount * -1), 0)
FROM gl a1
LEFT OUTER JOIN fiscal f ON a1.fiscalId=f.Id
WHERE
a1.companyId = a.companyId AND
a1.profitCenterId = a.profitCenterId AND
a1.coaId = a.coaId AND
f.Id > a.fiscalId - 12 AND
f.Id <= a.fiscalId
)
FROM gl a
INNER JOIN coa c ON c.Id=a.coaId AND c.statementType=4
GROUP BY companyId,profitCenterId,coaId,a.fiscalId
)AS Der
ON Num.Fiscal=Der.fiscalId

Related

SQL Server rows count return with inner join more than once in same table

I have this code
select
count(cat_item_tb.item_id),
count(t.item_id)
from
cat_tb
inner join
item_tb on cat_tb.cat_id = item_tb.cat_id
inner join
cat_item_tb on item_tb.item_id = cat_item_tb.item_id and t.ss = 0
inner join
cat_item_tb t on item_tb.item_id = t.item_id and t.ss = 1
All I need to return value without duplicate. In past code it must return 7 in every count but it's return 49 the two count() affected each other. I use distinct but it does not return the correct count, because there is (item_id) more than once in table
Thank you so much
Seems to me that you need to count distinct, to count the unique values
...
count(DISTINCT cat_item_tb.item_id)
...
The 2 counts in your query will be the same. That's simply because you INNER JOIN on those item_id's. So they will be identical by defenition.
If I understand correctly the task, you could use groub by to get desired results
select count(cat_item_tb.item_id), cat_item_tb.ss
from cat_tb
inner join item_tb on cat_tb.cat_id = item_tb.cat_id
inner join cat_item_tb on item_tb.item_id = cat_item_tb.item_id
where t.ss = 0 or t.ss = 1
group by cat_item_tb.ss
The query will return 2 rows with count values in first column.
More info about group by is here link
I believe you wanted to write something like:
select
count(c1.item_id),
count(c2.item_id)
from
cat_tb as a
inner join item_tb as b on ( a.cat_id = b.cat_id )
inner join cat_item_tb as c1 on ( b.item_id = c1.item_id ) and ( c1.ss = 0 )
inner join cat_item_tb as c2 on ( b.item_id = c2.item_id ) and ( c2.ss = 1 )
This won't work because of the inner joins. If the first join of c1 returns 3 rows and the second join of c2 returns 4 rows, you end up with count = 3*4
Try this:
;with cte1 as (
select
b.item_id,
'c1_count' = count( c1.item_id )
from
item_tb as b
left join cat_item_tb as c1 on ( b.item_id = c1.item_id ) and ( c1.ss = 0 )
group by
b.item_id
),
cte2 as (
select
b.item_id,
'c2_count' = count(c2.item_id)
from
item_tb as b
left join cat_item_tb as c2 on ( b.item_id = c2.item_id ) and ( c2.ss = 1 )
group by
b.item_id
)
select
a.item_id, a.c1_count, b.c2_count
from
cte1 as a
inner join cte2 as b on ( b.item_id = a.item_id )
For performance reasons you could replace the left join in ctes with inner join ONLY if you are sure that there are rows in cat_item_tb with item_id and all of them has the ss column set to 0 or 1.

Group BY Expression column

we're trying to make our table add together all values in column 2 (QtyComp - an expression column of qtyorder * totalqty basically), where they have the same ItemNo (column 1).
So, we currently get the below:
ItemNo QtyCom
7441 3
7441 1
7441 5
What we want is it to return this:
ItemNo QtyCom
7441 9
Our code is below; I've bolded the part that we need it to sum the results of:
SELECT TOP (100) PERCENT ItemSpecs_2.itemno,
workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 )
GROUP BY ItemSpecs_2.itemno,
workorderdetails.qtyordered,
ItemSpecFullStruc_2.totalqtyperroot,
workorderdetails.[lineno],
workorderdetails.qtycomplete,
workorderdetails.compdate,
workorderdetails.qtycomplete * ItemSpecFullStruc_2.totalqtyperroot
We would really appreciate some ideas!
Thanks,
Trish
Try this
SELECT TOP (100) PERCENT ItemSpecs_2.itemno,
sum(workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot) AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 )
GROUP BY ItemSpecs_2.itemno,
workorderdetails.qtyordered,
ItemSpecFullStruc_2.totalqtyperroot,
workorderdetails.[lineno],
workorderdetails.qtycomplete,
workorderdetails.compdate
Once you will use top for select statement, you need to use order by. you can try the following query.
SELECT TOP(100) PERCENT A.itemno,SUM(QtyComp) FROM
(SELECT ItemSpecs_2.itemno,
(workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot) AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 ) ) A
GROUP BY A.itemno
ORDER BY A.itemno
Thanks
SELECT SUM(QTYCOM) OVER (PARTITION BY ITEMNO)
FROM
...

Sum of resulting set of rows in SQL

I've got the following query:
SELECT DISTINCT CU.permit_id, CU.month, /*CU.year,*/ M.material_id, M.material_name, /*MC.chemical_id, C.chemical_name,
C.precursor_organic_compound, C.non_precursor_organic_compound,*/
/*MC.chemical_percentage,*/
POC_emissions =
CASE
WHEN (C.precursor_organic_compound = 'true')
THEN (CU.chemical_usage_lbs / CU.material_density) * M.VOC
ELSE 0
END,
NON_POC_emissions =
CASE
WHEN (C.non_precursor_organic_compound = 'true')
THEN CU.chemical_usage_lbs * (MC.chemical_percentage / 100)
ELSE 0
END
FROM material M
LEFT OUTER JOIN material_chemical MC ON MC.material_id = M.material_id
LEFT OUTER JOIN chemical_usage CU ON CU.material_id = MC.material_id
LEFT OUTER JOIN chemical C ON C.chemical_id = MC.chemical_id
WHERE (CU.month >=1 AND CU.month <= 2)
AND CU.year = 2013
AND M.material_id = 52
--AND CU.permit_id = 2118
--GROUP BY CU.permit_id, M.material_id, M.material_name, CU.month, MC.chemical_id, MC.chemical_id, C.chemical_name, C.precursor_organic_compound, C.non_precursor_organic_compound
--ORDER BY C.chemical_name ASC
Which returns:
But what I need is to return one row per month per material adding up the values of POC per month and NON_POC per month.
So, I should end up with something like:
Month material_id material_name POC NON_POC
1 52 Krylon... 0.107581 0.074108687
2 52 Krylon... 0.143437 0.0988125
I tried using SUM but it sums up the same result multiple times:
SELECT /*DISTINCT*/ CU.permit_id, CU.month, /*CU.year,*/ M.material_id, M.material_name, /*MC.chemical_id, C.chemical_name,
C.precursor_organic_compound, C.non_precursor_organic_compound,*/
--MC.chemical_percentage,
POC_emissions = SUM(
CASE
WHEN (C.precursor_organic_compound = 'true')
THEN (CU.chemical_usage_lbs / CU.material_density) * M.VOC
ELSE 0
END),
NON_POC_emissions = SUM(
CASE
WHEN (C.non_precursor_organic_compound = 'true')
THEN CU.chemical_usage_lbs * (MC.chemical_percentage / 100)
ELSE 0
END)
FROM material M
LEFT OUTER JOIN material_chemical MC ON MC.material_id = M.material_id
LEFT OUTER JOIN chemical_usage CU ON CU.material_id = MC.material_id
LEFT OUTER JOIN chemical C ON C.chemical_id = MC.chemical_id
WHERE M.material_id = 52
--AND CU.permit_id = 187
AND (CU.month >=1 AND CU.month <= 2)
AND CU.year = 2013
GROUP BY CU.permit_id, M.material_id, M.material_name, CU.month/*, CU.year, MC.chemical_id, C.chemical_name, C.precursor_organic_compound, C.non_precursor_organic_compound*/
--ORDER BY C.chemical_name ASC
The first query has a DISTINCT clause. What is the output without the DISTINCT clause. I suspect you have more rows than shows in your screenshot.
Regardless, you could try something like this to get the desired result.
select permit_id, month, material_id, material_name,
sum(poc_emissions), sum(non_poc_emissions)
from (
SELECT DISTINCT CU.permit_id, CU.month, M.material_id, M.material_name,
POC_emissions =
CASE
WHEN (C.precursor_organic_compound = 'true')
THEN (CU.chemical_usage_lbs / CU.material_density) * M.VOC
ELSE 0
END,
NON_POC_emissions =
CASE
WHEN (C.non_precursor_organic_compound = 'true')
THEN CU.chemical_usage_lbs * (MC.chemical_percentage / 100)
ELSE 0
END
FROM material M
LEFT OUTER JOIN material_chemical MC ON MC.material_id = M.material_id
LEFT OUTER JOIN chemical_usage CU ON CU.material_id = MC.material_id
LEFT OUTER JOIN chemical C ON C.chemical_id = MC.chemical_id
WHERE (CU.month >=1 AND CU.month <= 2)
AND CU.year = 2013
AND M.material_id = 52
) main
group by permit_id, month, material_id, material_name
Explanation
Since the results you retrieved by doing a DISTINCT was consider source-of-truth, I created an in-memory table by making it a sub-query. However, this subquery must have a name of some kind...whatever name. I gave it a name main. Subqueries look like this:
select ... from (sub-query) <give-it-a-table-name>
Simple Example:
select * from (select userid, username from user) user_temp
Advanced Example:
select * from (select userid, username from user) user_temp
inner join (select userid, sum(debits) as totaldebits from debittable) debit
on debit.userid = user_temp.userid
Notice how user_temp alias for the subquery can be used as if the sub-query was a real table.
Use above query in subquery and group by (month) and select sum(POC_emissions) and sum(NON_POC_emissions )

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

Select only the rows where column values appear more than once

I have a select statement similar to the following:
select *
from A
inner join B on A.id_x = B.id_x
inner join C on B.id_y = C.id_y
inner join D on C.id_z = D.id_z
where
A.date > '2014-01-01'
and A.id_y = 154
and D.id_t = 2
What I want is to do something like this and count(A.id_x) > 1, which returns only the parts of the original select which repeat on A.id_x.
Is this possible?
EDIT:
I just tried to solve it using temp tables, with the code I got from T-SQL Insert into table without having to specify every column
Select * Into
#tmpBigTable
From [YourBigTable]
But I got an error message because my tables have the same column names, A.id_x and B.id_x, for example.
"Column names in each table must be unique."
Is there some way to force the issue, or declare arbitrary naming extensions?
select *
from A
inner join B on A.id_x = B.id_x
inner join C on B.id_y = C.id_y
inner join D on C.id_z = D.id_z
where
A.date > '2014-01-01'
and A.id_y = 154
and D.id_t = 2
AND A.id_x IN
(
SELECT A.id_x FROM A
GROUP BY A.id_x
HAVING count(A.id_x)>1);
You can do this with window functions:
select *
from (select *, count(*) over (partition by A.id_x) as cnt
from A inner join
B
on A.id_x = B.id_x inner join
C
on B.id_y = C.id_y inner join
D
on C.id_z = D.id_z
where A.date > '2014-01-01' and A.id_y = 154 and D.id_t = 2
) abcd
where cnt > 1;