Trying to create fields based on a case statement - sql

I'm having some trouble with the query below. I am trying to determine if the "category" field is A, B or C and then creating a field based on the category. That field would sum up payments field. But I'm running into error saying "incorrect syntax near keyword As". I am creating this in a SQL View. Using SQL Server 2008
SELECT r.id, r.category
CASE
WHEN r.category = 'A' then SUM(r.payment) As A_payments
WHEN r.category = 'B' then SUM(r.payment) As B_payments
WHEN r.category = 'C' then SUM(r.payment) As C_payments
END
FROM r_invoiceTable As r
GROUP BY r.id, r.category
I have data where all of the above cases should be executed because the data that I have has A,B and C
Sample Data- r_invoiceTable
Id --- Category ---- Payment
222 A ---- 50
444 A ---- 30
111 B ---- 90
777 C ---- 20
555 C ---- 40
Desired Output
A_payments = 80, B_payments = 90, C_payments = 60

Perhaps you are looking for this:
SELECT
SUM(CASE WHEN category = 'A' THEN payment END) AS A_payments,
SUM(CASE WHEN category = 'B' THEN payment END) AS B_payments,
SUM(CASE WHEN category = 'C' THEN payment END) AS C_payments
FROM r_invoiceTable

May be you want this (category-wise payment sum)?:
SELECT r.category, SUM(r.payment) As Payments
FROM r_invoiceTable As r
GROUP BY r.category
Output will be like:
category Payments
--------- ------------
A 80
B 90
C 60
If you like these numbers in a single row here is a naive approach:
SELECT
(SELECT SUM(r.payment) From r_invoiceTable As r Where r.category = 'A') as A_Payment,
(SELECT SUM(r.payment) From r_invoiceTable As r Where r.category = 'B') as B_Payment,
(SELECT SUM(r.payment) From r_invoiceTable As r Where r.category = 'C') as C_Payment

SELECT *
FROM dbo.r_invoiceTable
PIVOT
( SUM(payment)
FOR category IN ([a],[b],[c])
) AS pivoted

Related

How to sum() if missing data in same column in SQL

I need to sum up the quantity according to typein the table below.
Table
Name Quantity Type
a 6 AB
b 2 BB
b 4 AB
c 8 BB
a 3 BB
b 5 AB
Outcome
Name AB_Type BB_Type
a 6 3
b 9 2
c 0 8
I am trying the below query but I can't get the numbers right.
SELECT S.Name, SUM(S1.Quantity) AS AB_Type, SUM(S2.Quantity) AS BB_Type
FROM Table AS S, Table AS S1, Table AS S2
WHERE S.Name = S1.SName = S2.Name AND S1.Type = 'AB'AND S2.Type = 'BB'
GROUP BY S.Name;
Thanks in advance!!
Try this
SELECT
Name,
SUM(CASE WHEN Type = 'AB' THEN Quantity ELSE 0 END) AS AB_Type,
SUM(CASE WHEN Type = 'BB' THEN Quantity ELSE 0 END) AS BB_Type
FROM Table
GROUP BY Name
you can use pivot as follows:
SELECT Name,
iif(AB_Type is null,0,AB_Type) AB_Type,
iif(BB_Type is null,0,BB_Type) BB_Type
FROM (
SELECT
Name
,Quantity
,CONCAT(Type, '_type') AS Col
FROM table
) Src
PIVOT (
sum(Quantity)
FOR Col IN (
[AB_Type], [BB_Type]
)
) Pvt

query returning duplication's despite nested query returning no duplicates

I have the following query below which works. However it is return duplicates which I don't understand.
The first three nested queries return no duplicates so I don't understand why the end result has duplicates sedols?
;with b as
(
select sedol, wgt from myTbl
where name = 'B'
), j as
(
select sedol, wgt from myTbl
where name = 'J'
), s as
(
select sedol, wgt from myTbl
where name = 'S'
), hlds as
(
select coalesce(b.sedol, j.sedol, s.sedol) sedol, isnull(b.wgt,0) bw, isnull(j.wgt,0) jw, isnull(s.wgt,0) sw
from b full outer join j on b.sedol = j.sedol
full outer join s on b.sedol = s.sedol
)
select hlds.* from hlds
order by sedol
sample data
myTbl
sedol name wgt
abc b 1
abc j 2
abc s 3
def j 2
def s 4
current result
abc 1 2 3
def 0 2 0
def 0 0 4
should be
abc 1 2 3
def 0 2 4
Lets improve this query and save the joins with conditional aggregation:
SELECT t.sedol,
MAX(CASE WHEN t.name = 'B' THEN t.wgt END) as [b],
MAX(CASE WHEN t.name = 'J' THEN t.wgt END) as [j],
MAX(CASE WHEN t.name = 'S' THEN t.wgt END) as [s]
FROM YourTable t
GROUP BY t.sedol

SQL query to compare subsets of rows between each other

There is an SQL query I'm after (in SQL Server). I need to get the count of instances where company Y is more expensive than company X. How would I start to tackle this? I've looked through various examples, but I cannot find anything similiar. I see PARTITION BY could be helpful, but not sure how to start from there - any hint will be very helpful.
ReadingId | Product | Price | Company
----------------------------------------------
1 | A | 3 | X
2 | A | 4 | Y
3 | A | 5 | Z
4 | B | 11 | X
5 | B | 12 | Y
6 | B | 13 | Z
...
One method is conditional aggregation. For each product:
select product,
max(case when company = 'Y' then price end) as Yprice
max(case when company = 'X' then price end) as Xprice
from t
group by product;
For a count, you can then do:
select count(*)
from (select product,
max(case when company = 'Y' then price end) as Yprice
max(case when company = 'X' then price end) as Xprice
from t
group by product;
) p
where Yprice > Xprice;
There are other methods as well. Pivot can be used, as well as a join with aggregation:
select count(*)
from t ty join
t tx
on ty.company = 'Y' and tx.company = 'X' and ty.product = tx.product
where ty.price > tx.price;
I should point out that all these methods sort of assume that X and Y only appear once for each product. That seems reasonable given your data.
Rather straight-forward. Get product prices for companies X and Y. Join them together on product and compare prices.
It assumes that each product is listed once for a company.
WITH
CTE_X
AS
(
SELECT Product, Price
FROM T
WHERE Company = 'X'
)
,CTE_Y
AS
(
SELECT Product, Price
FROM T
WHERE Company = 'Y'
)
SELECT COUNT(*) AS cc
FROM
CTE_X
INNER JOIN CTE_Y ON CTE_Y.Product = CTE_X.Product
WHERE
CTE_Y.Price > CTE_X.Price
;
You can do this with conditional aggregation.
with xandy as (select product,
max(case when company = 'X' then price end) as xprice,
max(case when company = 'Y' then price end) as yprice
from tablename
group by product)
select count(*)
from xandy
where yprice > xprice
This query, tho not efficient, will give you the details of what you need:
Select
CompanyY.*,
CompanyX.*
FROM
(
select * from OrderDetails
where Company = 'Y'
) CompanyY
JOIN
(
select * from OrderDetails
where Company = 'X'
) CompanyX
ON CompanyX.Product = CompanyY.Product
WHERE CompanyY.Price > CompanyX.Price
Try the SQLFiddle Here
You can use:
SELECT COUNT(*)
FROM (
SELECT Product
FROM mytable
GROUP BY Product
HAVING MAX(CASE WHEN Company = 'Y' THEN Price END)
>
MAX(CASE WHEN Company = 'X' THEN Price END) ) AS t
The sub-query returns the list of products where company Y is more expensive than company X. The outer query simply counts the number of these products.
Yet another version using a window function:
SELECT COUNT(*)
FROM (
SELECT Company,
ROW_NUMBER() OVER (PARTITION BY Product
ORDER BY Price DESC) AS rn
FROM mytable
WHERE Company IN ('X', 'Y')) AS t
WHERE t.rn = 1 AND Company = 'Y'
The sub-query filters out any rows not having either 'X' or 'Y' as their Company. The outer query counts the number of rows for which Company = 'Y' has the highest price.

Finding value when multiple rows by group by

Lets say we have the following data sets
tbl_building:
id -- name
1 -- building 1
2 -- building 2
tbl_rooms:
id -- building_id -- room_id -- light_status
1 ------ 1 ------------- 1 ----------- 0
2 ------ 1 ------------- 2 ----------- 1
3 ------ 1 ------------- 3 ----------- 0
4 ------ 2 ------------- 1 ----------- 1
How would I construct a single sql statement to find out which BUILDINGS have a light switched on in a YES/NO format Whilst grouping by Building name
Idealling I want something like the following:
SELECT b.name, if(light_status, 'yes', no) as light_status
FROM tbl_building b
JOIN tbl_rooms r on b.id = r.building_id
group by b.id
However, this seems to be random as to which room it will bring back for each buildinh
Select b.name, case when sum (a.light_status) > 0 then 'YES' else 'NO' end as LightStatus
From tbl_rooms a
Join tbl_buildings b
On a.building_id = b.building_id
Group by b.name
A simple case for a semi-join:
SELECT name
FROM tbl_building b
WHERE EXISTS (
SELECT 1
FROM tbl_rooms r
WHERE b.id = r.building_id
AND light_status = 1
)
This will return those buildings where at least one room has their light switched on.
select (case when tbl_rooms.light_status = 1 then building_id end) as building_id_on,
(case when tbl_rooms.light_status = 0 then building_id end) as building_id_on
from tbl_building inner join tbl_rooms on tbl_building.id = tbl_rooms.building_id
Try this:
SELECT DISTINCT B.name
FROM tbl_rooms A
INNER JOIN tbl_builiding B
ON A.building_id = B.id
To find buildings with at least one room with the lights turned on:
SELECT
B.name
FROM tbl_rooms A
INNER JOIN tbl_builiding B
ON A.building_id = B.id
GROUP BY B.name
HAVING MAX(light_status) = 1
To list all buildings and wether or not they have at least one room with the light turned on:
SELECT
B.name, IIF(MAX(light_status) = 1, 'YES', 'NO') as light_status
FROM tbl_rooms A
INNER JOIN tbl_builiding B
ON A.building_id = B.id
GROUP BY B.name

Performing additions within multiple columns of different rows in a SQL Server table based on the text in a column

I am trying to figure a query which performs some additions and subtractions of data in different rows and different columns based on the text/data in some other column in the same table.
Problem can be clearly addressed with the following example
Consider, I have table named Outright with four fields/columns with several records as follows
Product Term Bid Offer
------------------------------
A Aug14 P Q
A/B Aug14 R S
B Aug14 X Y
B Sep14 ab xy
B/C Sep14 pq rs
C Sep14 wx yz
When I run the query it should look for the Products that is separated by / in the above case there are two products of that type A/B and B/Cand then it should look for individual products based the those that are separated by / like we have a product A/B which is separated by a /, so it should look for product A and B with same term as A/B and perform some operations and return the data as follows
Product Term Bid Offer
------------------------------
A Aug14 a b
B Aug14 c d
B Sep14 ab cd
C Sep14 abc cde
in the above results
a=R+Y b=S+X
c=Q-S d=P-R
where P,Q,R,S,X,Y are Bid and Offer values from the table Outright
similar calculations are applied for all other data too like for B/C Sep14.. and many other
Example
Table Outright
A Oct14 -175 -75
B Oct14 125 215
A/B Oct14 NULL -150
Result should be
A Oct14 NULL -150+125=-25
B Oct14 -75-(-150)=75 NULL
The above values are calculated using the equations mentioned earlier
May I know a better way to solve it in SQL Server 2012?
Ok lets create some test data:
DECLARE #Outright TABLE
(
Product VARCHAR(10),
Term VARCHAR(10),
Bid VARCHAR(10),
Offer VARCHAR(10)
)
INSERT INTO #Outright
VALUES
('A', 'Aug14','P','Q'),
('A/B','Aug14','R','S'),
('B', 'Aug14','X','Y');
Making a cte to try to figure out the logic posted above and match the single product line to the multiproduct line
;WITH t AS
(
SELECT
a.*,
d.DRN,
d.Bid dBid,
d.Product dProduct,
d.Offer dOffer,
ROW_NUMBER() OVER (ORDER BY a.Product) RN
FROM #Outright a
OUTER APPLY
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY d.Product) DRN
FROM #Outright d
WHERE d.Product LIKE (a.Product + '/%')
OR d.Product LIKE ('%/' + a.Product)
) d
WHERE d.Product IS NOT NULL
)
Now we try to implement the + - rules as stated above (bids to offers, offers to bids, etc)
SELECT
*,
CASE WHEN RN = 1 THEN FE1_1 + '+' + FE1_2 ELSE FE1_1 + '-' + FE1_2 END Col1,
CASE WHEN RN = 1 THEN FE2_1 + '+' + FE2_2 ELSE FE2_1 + '-' + FE2_2 END Col2
FROM
(
SELECT
MAX(CASE WHEN RN = 1 THEN Product END) Prod1,
MAX(CASE WHEN RN = 1 THEN Term END) Term1,
MAX(CASE WHEN RN = 1 THEN dBid END) FE1_1,
MAX(CASE WHEN RN = 2 THEN Offer END) FE1_2,
MAX(CASE WHEN RN = 2 THEN dOffer END) FE2_1,
MAX(CASE WHEN RN = 2 THEN Bid END) FE2_2,
1 RN
FROM t
UNION ALL
SELECT
MAX(CASE WHEN RN = 2 THEN Product END) Prod2,
MAX(CASE WHEN RN = 2 THEN Term END) Term2,
MAX(CASE WHEN RN = 1 THEN Offer END) FE3_1,
MAX(CASE WHEN RN = 2 THEN dOffer END) FE3_2,
MAX(CASE WHEN RN = 1 THEN Bid END) FE4_1,
MAX(CASE WHEN RN = 2 THEN dBid END) FE4_2,
2 RN
FROM t
) d
Here is the output, with some extra columns to show the data being pulled
Prod1 Term1 FE1_1 FE1_2 FE2_1 FE2_2 RN Col1 Col2
A Aug14 R Y S X 1 R+Y S+X
B Aug14 Q S P R 2 Q-S P-R