I have two queries in SQL:
Query A:
SELECT column_1, column_2, column_3 FROM a
Query B
SELECT column_1, column_2, column_3 FROM b
I want to add another column in a such that the column represent the SUM of all values from b.column_3 where b.column_1 = a.column_1
How can this be done in SQL Server?
This will give you all rows you needed:
SELECT *
FROM a
LEFT JOIN b -- left join because for some of the rows in "a" there will be not row in "b"
ON a.column_1 = b.column_1 -- your first condition
OR a.column_2 = b.column_2 -- your second condations
Then we just need to perform the sum:
SELECT a.column_1
,a.column_2
,a.column_3
,SUM(CASE WHEN b.column_1 IS NOT NULL AND a.column_1 = b.column_1 THEN b.column_3 ELSE 0 END)
,SUM(CASE WHEN b.column_1 IS NOT NULL AND a.column_2 = b.column_2 THEN b.column_3 ELSE 0 END)
FROM a
LEFT JOIN b
ON a.column_1 = b.column_1
OR a.column_2 = b.column_2
GROUP BY a.column_1
,a.column_2
,a.column_3
A join with aggregation should work here:
SELECT
a.column_1,
a.column_2,
a.column_3,
b.b_sum
FROM a
LEFT JOIN
(
SELECT column_1, SUM(column_3) AS b_sum
FROM b
GROUP BY column_1
) b
ON a.column_1 = b.column_1;
Related
SELECT id,
login_id,
count,
case when count = 0 then 'Cat_A'
WHEN count between 1 and 10 then 'Cat_B'
WHEN count > 10 then 'Cat_C'
WHEN count IS NULL THEN 'Cat D'
END as Category
FROM
(
select id,login_id,min(ord_count) AS count
FROM table_1 X
JOIN table_2 Y
ON X.id_col = Y.id_col
WHERE date = '2022-02-02'
AND login_id = 'True'
group by id,login_id
)A
LEFT JOIN
(
SELECT id,COUNT(X.ord_no) AS count_of_orders
FROM table_1 X
WHERE X.date = '2022-02-02'
group by id
)B
ON A.id=B.id
When I join these two tables, I'm getting NULL values for the unmatched records.
I need to replace those NULL records to some hardcoded value say 'XYZ'.
Any guidance on how to achieve this please?
So the top level select needs to name which ID it is using (other DB's don't require this snowflake does), given you are selecting from A and b.id might be missing, it should be a.id
count_of_orders is not used, so currently the LEFT JOIN to B is pointless, given your question is about LEFT JOIN this must be the column you a referring to??
The replace NULL values can be done via COALESCE or NVL or ZEROIFNULL, given the only null thing is a count, zeroifnull seems to make sense here.
which all make me think your SQL needs to look like:
SELECT
a.id,
a.login_id,
a.count,
case
WHEN a.count = 0 then 'Cat_A'
WHEN a.count between 1 and 10 then 'Cat_B'
WHEN a.count > 10 then 'Cat_C'
WHEN a.count IS NULL THEN 'Cat D'
END as Category,
ZEROIFNULL(b.count_of_orders) as count_of_orders
FROM (
SELECT
id,
login_id,
min(ord_count) AS count
FROM table_1 AS X
JOIN table_2 AS Y
ON X.id_col = Y.id_col
WHERE date = '2022-02-02'
AND login_id = 'True'
group by id,login_id
) as A
LEFT JOIN (
SELECT
x.id,
COUNT(X.ord_no) AS count_of_orders
FROM table_1 as X
WHERE X.date = '2022-02-02'
group by x.id
)as B
ON A.id=B.id
The A sub-select really should use the aliases you named X, Y so we know which tables id, login_id, ord_count, & date all come from.
I am trying to obtain two different counts in a query. One count would be the count of the specific item in one table, and the other count would be the same but from a different table. I can write 2 different queries that provides me the info but in two different tables. I would like to write one query that puts it all into one table. Thank you guys for any of suggestions.
EDIT: To clarify, I would like to add the count from the second query to a column on the first query.
My query
select d.description, count(item_id) from productdetails pd
join inventory i on i.itemnum=pd.item_id
join departments d on d.dept_id=i.dept_id
where i.last_sold is not null and in_stock !=0
group by d.description
select d.description, count(itemnum)
from inventory i
join departments d on d.dept_id=i.dept_id
where in_stock != 0 and last_sold is not null
group by d.description
Place your queries in a sub-query where each count has been established and the "missing" count is assigned a value of zero.
Next, sum the count.
SELECT smmry.description
, SUM(smmry.pd_item_cnt) pd_item_cnt
, SUM(smmry.itemnum_cnt) itemnum_cnt
FROM (
SELECT d.description
, COUNT(pd.item_id) pd_item_cnt
, 0 itemnum_cnt
FROM productdetails pd
JOIN inventory i
ON i.itemnum = pd.item_id
JOIN departments d
ON d.dept_id = i.dept_id
WHERE i.last_sold IS NOT NULL
AND in_stock != 0
GROUP BY d.description
UNION ALL
SELECT d.description
, 0 pd_item_cnt
, COUNT(i.itemnum) itemnum_cnt
FROM inventory i
JOIN departments d
ON d.dept_id = i.dept_id
WHERE in_stock != 0
AND last_sold IS NOT NULL
GROUP BY d.description
) smmry
GROUP BY smmry.description
WITH Query1 (Description1, Count1) AS (
select d.description, count(item_id) from productdetails pd
join inventory i on i.itemnum=pd.item_id
join departments d on d.dept_id=i.dept_id
where i.last_sold is not null and in_stock !=0
group by d.description
),
Query2 (Description2, Count2) AS (
select d.description, count(itemnum)
from inventory i
join departments d on d.dept_id=i.dept_id
where in_stock != 0 and last_sold is not null
group by d.description
)
SELECT Description1, Count1, Description2, Count2 FROM Query1, Query2
I am trying to write a query where I want to sum a price column based on the condition which is a subquery.
my query :
select
fund.FundName,
SUM(Case when (
Select Top 1 bitValue
from table 1
where table1.id = Company.id and table1.field = 25
) = 1 then price else 0 end) as 'TotalPrice'
from
Fund left outer join Company on Company.fundId=fund.id
group by
fund.fundName
It throws me error : Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
What is the best alternative way to achieve this.
Hope this Works for your Case:
SELECT
FUND.FUNDNAME,
S.TotalPrice
FROM FUND
LEFT OUTER JOIN COMPANY ON COMPANY.FUNDID=FUND.ID
LEFT JOIN (SELECT CASE WHEN BITVALUE=1 THEN SUM(PRICE) ELSE 0 END as 'TotalPrice',table1.ID
from table 1
where table1.id = Company.id and table1.field = 25 GROUP BY table1.ID
) S ON S.ID=Company.id
GROUP BY
FUND.FUNDNAME
untested obviously with no sample data provided.
select fund.FundName
,SUM(Case when table1.id is not null then price else 0 end) as 'TotalPrice'
from Fund
left outer join Company on Company.fundId = fund.id
left outer join (
select distinct id
from table1
where field = 25
and bitvalue = 1
) table1 on table1.id = Company.id
group by fund.fundName
I have Table A which have reference to Table B. Table B may have one or more entry for each record in A. In B I have a column as status. I want to choose one row by given condition below. Consider I have 3 entries in Table B
If status is OA or OB in any row, then select that row
If status is other than OA or OB then select any one row
My query
--lot more table joins already here
LEFT JOIN(
SELECT CASE WHEN EXISTS
( SELECT 1 FROM A a1 INNER JOIN B b1 ON a1.id = b1.id
WHERE b1.status in ('OA','OB'))
THEN (SELECT b1.rcid FROM A a1 INNER JOIN B b1 ON a1.id = b1.id
WHERE b1.status in ('OA','OB'))
ELSE
SELECT TOP 1 b2.rcid FROM A a2 INNER JOIN B b2 ON a2.id = b2.id
END
))Z on z.id=b2.id --again join with table for b2.rcid
Is this the correct way? Will it have a performance impact?. Really want to highlight here, in real I have to join almost 10 tables of which 5 will have 100 000+ records.
cross/outer apply (
select top 1 status
from B b
where b.id = a.id
order by case when status in ('OA', 'OB') then 1 else 2 end, status
)
or
inner/left join (
select
id,
case min(case when status in ('OA', 'OB') then 1 else 2 end)
when 1 then min(cast when status in ('OA', 'OB') then status end)
when 2 then min(status)
end
from B
group by id
) b on b.id = a.id
I would like to know if the following is possible in SQL server 2005. Column A and B are calculated using other case statements in my actual stored proc. I don't want to repeat the same for another field unnecessarily. If this is not syntactically possible, any other ideas?
SELECT A, B, CASE WHEN column1='1' THEN A ELSE B END Col1.
Modified version of actual query provided as requested. CTE kind of seems to be tough in this model. WANNABE is the column I want to accomplish in the sub select statement.
SELECT 1 AS Region, 'Test',
CAST(Work AS NUMERIC(18,2)) Work,
Work + 2 AS Work2,
WANNABE
FROM
(
SELECT
ROW_NUMBER() OVER(PARTITION BY G.Value, C.C, FR.Mod1 ORDER BY FR.Date DESC, FG.Date DESC, FC.Date DESC) ROW,
CASE WHEN COALESCE(FR.Mod1, '') = '' THEN '' ELSE FR.Mod1 END Mod1,
CASE WHEN #var1=1 AND #var2 = 1 THEN FR.Col1 * G.Value
WHEN #var1=1 AND #var2 = 0 THEN FP.Col1 * G.Value END Work,
CASE WHEN 1=1 THEN Work ELSE 1 END WANNABE,
(
SELECT Col3
FROM Table2
WHERE c = FR.Value
) AS Custom
FROM MainTable FR
JOIN #C C ON FR.Col2 = C.Col2
LEFT JOIN Function1(#VersionDate) cv ON cv.Code = C.Code
LEFT JOIN Function2(#VersionDate) hv ON hv.Code = C.Code
LEFT JOIN #G G ON 1 = 1
LEFT JOIN SubTable1 FG ON FG.Number = G.Value, 2 AND FG.Date = #VersionDate
LEFT JOIN SubTable2 FO ON FO.Number = G.Value
AND FO.Date = #VersionDate AND FO.Code = FR.Code AND FR.Mod1 = FO.Mod1
LEFT JOIN SubTable3 FP ON FP.Code = FR.Code AND FP.VersionDate = #Versiondate
AND CASE WHEN DATALENGTH(FR.Mod1) = 0 THEN '00' ELSE FR.Mod1 END = CASE WHEN DATALENGTH(FP.Mod1) = 0 THEN '00' ELSE FP.Mod1 END
LEFT JOIN SubTable4 FC ON FC.Date = #VersionDate
WHERE FR.Date = #VersionDate
) x
WHERE x.Row = 1
AND RTRIM(LTRIM(x.Col1)) IN ('', '2')
You can define the A,B column aliases in a CTE then reference them in an outer select.
;WITH CTE AS
(
SELECT CASE ... END AS A,
CASE ... END AS B,
column1
FROM your_table
)
SELECT A,
B,
CASE WHEN column1='1' THEN A ELSE B END Col1
FROM CTE
Similarly you can also define them in a CROSS APPLY that is sometimes a bit less verbose.
A silly example just to show the syntax is
SELECT A,
B,
CASE WHEN type='P' THEN A ELSE B END Col1
FROM master..spt_values
CROSS APPLY (SELECT CASE WHEN number %2 = 1 THEN 1 END,
CASE WHEN number %2 = 0 THEN 0 END) T(A,B)
Following your update you can replace the derived table with a CTE and nest CTEs as follows
;WITH x as
(
SELECT
ROW_NUMBER() OVER(PARTITION BY G.Value, C.Code, FR.Mod1 ORDER BY FR.Date DESC, FG.Date DESC, FC.Date DESC) ROW,
...<snip>
WHERE FR.Date = #VersionDate
),
x2 As
(
SELECT *,
CASE WHEN 1=1 THEN Work ELSE 1 END WANNABE
FROM x
)
SELECT 1 AS Region, 'Test',
CAST(Work AS NUMERIC(18,2)) Work,
Work + 2 AS Work2,
WANNABE
FROM x2
WHERE x2.Row = 1
AND RTRIM(LTRIM(x2.Col1)) IN ('', '2')
Yeah it is posible, but how is all your sql statement? You can use the case statement in the select statement as you are using it.
Something like this
SELECT SUM((CASE WHEN column1='1' THEN 10 ELSE 0 END)) AS A, SUM((CASE WHEN column1='2' THEN 10 ELSE 0 END)) AS B
FROM YourTable