How to Sum a result quantity in sql server with multiple records which several joins, does it need some subquery to do it? - sql

I am wanting to get the SUM records of a query that I am writing
I have done simple SUM aggregates in the past, but I'm a bit rusty and wonder the best approach to getting the proper results.
Example of table with Quantity (imaps_inv)
ste_id ste_acct_id stk_id qty
1 1 001 5
1 2 001 10
1 3 001 15
So the query should NOT return 3 records, but only 1 record and so the query results SHOULD be
Site ID Stocking ID Qty
1 001 30
So you can see what I want to return
inv.qty is the Quantity field I wish to SUM , and the query I wrote up based on the tables is below.
SELECT ste.ste_id, ty.ste_ty_id, inv.qty
FROM dbo.imaps_inv inv WITH(NOLOCK)
INNER JOIN dbo.imaps_ste ste WITH(NOLOCK)
ON inv.ste_id = ste.ste_id
INNER JOIN dbo.imaps_ste_ty ty
ON ty.ste_ty_id = ste.ste_ty_id
INNER JOIN dbo.imaps_stk_acct acct WITH(NOLOCK)
ON acct.ste_id = ste.ste_id
INNER JOIN dbo.imaps_stk_acct_ty aty WITH(NOLOCK)
ON aty.stk_acct_ty_id = acct.stk_acct_ty_id
WHERE
ste.inact_ind = 0
AND LTRIM(RTRIM(aty.stk_acct_ty_nm)) = 'Good'
AND acct.rsv_ind = 0
AND acct.inact_ind = 0
PLEASE LET ME KNOW WHAT I CAN PROVIDE TO MAKE IT MORE HELPFUL ( screenshots, schema etc... )
UPDATE,
well I was only getting 19 records and this co-worker said "oh, no.. you should be getting 16,000 records...
I said ok, i'm using this ste_id (site id) and when I sent him this query
SELECT distinct ste_id from [dbo].[imaps_inv] ( 20 records)
He said, to add in stk_id (stock #)
SELECT distinct ste_id, stk_id from [dbo].[imaps_inv] (15,910 records)
Therefore I updated my query to which I finally have the proper results and figured I would update my question with the combination of the persons answer along with me tweaking the code as other person certainly does not have the schema and records etc..
Final working query
SELECT ste.ste_id as 'Site ID', inv.stk_id as 'Stocking ID', SUM(inv.qty) Qty
FROM dbo.imaps_inv inv WITH(NOLOCK)
INNER JOIN dbo.imaps_ste ste WITH(NOLOCK)
ON inv.ste_id = ste.ste_id
INNER JOIN dbo.imaps_ste_ty ty
ON ty.ste_ty_id = ste.ste_ty_id
INNER JOIN dbo.imaps_stk_acct acct WITH(NOLOCK)
ON acct.ste_id = ste.ste_id
INNER JOIN dbo.imaps_stk_acct_ty aty WITH(NOLOCK)
ON aty.stk_acct_ty_id = acct.stk_acct_ty_id
WHERE
ste.inact_ind = 0
AND LTRIM(RTRIM(aty.stk_acct_ty_nm)) = 'Good'
AND acct.rsv_ind = 0
AND acct.inact_ind = 0
GROUP BY ste.ste_id, inv.stk_id

Use SUM:
SELECT ste.ste_id,
SUM(inv.qty) Qty
FROM dbo.imaps_inv inv WITH(NOLOCK)
INNER JOIN dbo.imaps_ste ste WITH(NOLOCK)
ON inv.ste_id = ste.ste_id
INNER JOIN dbo.imaps_ste_ty ty
ON ty.ste_ty_id = ste.ste_ty_id
INNER JOIN dbo.imaps_stk_acct acct WITH(NOLOCK)
ON acct.ste_id = ste.ste_id
INNER JOIN dbo.imaps_stk_acct_ty aty WITH(NOLOCK)
ON aty.stk_acct_ty_id = acct.stk_acct_ty_id
WHERE
ste.inact_ind = 0
AND LTRIM(RTRIM(aty.stk_acct_ty_nm)) = 'Good'
AND acct.rsv_ind = 0
AND acct.inact_ind = 0
GROUP BY ste.ste_id;

Related

postgresql count distinct on differect condition

I'm stuck on an exercise where I need to count the total amount of unique visits to planets, but if the planet is the moon (maan), then it should be counted twice. Also the client number should be 121
select case
when objectnaam = 'Maan' then count(objectnaam)
else count(distinct objectnaam)
end as aantal_bezoeken
from klanten inner join deelnames on klanten.klantnr = deelnames.klantnr
inner join reizen on deelnames.reisnr = reizen.reisnr
inner join bezoeken on reizen.reisnr = bezoeken.reisnr
where klanten.klantnr = 121
group by objectnaam
And it gives me this result
aantal_bezoeken
1
4
1
1
but the result should be
aantal_bezoeken
7
I just need to add all these values together but I don't know how to,
or maybe there's a better more simple solution. It should be without subqueries
Try this:
select sum(aantal_bezoeken) as aantal_bezoeken from
(select case
when objectnaam = 'Maan' then count(objectnaam)
else count(distinct objectnaam)
end as aantal_bezoeken
from klanten inner join deelnames on klanten.klantnr = deelnames.klantnr
inner join reizen on deelnames.reisnr = reizen.reisnr
inner join bezoeken on reizen.reisnr = bezoeken.reisnr
where klanten.klantnr = 121
group by objectnaam) as a

SQL Query to retrieve single record per filter

I have the following query:
SELECT min(salesorder.SOM_SalesOrderID) AS salesorder,
Item.IMA_ItemID,
Item.IMA_ItemName,
Customer.CUS_CorpName,
WK.WKO_WorkOrderID,
min(WK.WKO_OrigRequiredDate),
WK.WKO_WorkOrderTypeCode,
min(WK.WKO_RequiredDate),
max(WK.WKO_LastWorkDate),
min(wk.WKO_RequiredQty),
wk.WKO_MatlIssueDate,
min(SalesOrderDelivery.SOD_RequiredQty),
Item.IMA_ItemTypeCode,
Item.IMA_OnHandQty,
min(SalesOrderDelivery.SOD_PromiseDate),
min(WO.woo_operationseqID) AS seqid
FROM SalesOrder
INNER JOIN SalesOrderLine ON SalesOrder.SOM_RecordID = SalesOrderLine.SOI_SOM_RecordID
INNER JOIN SalesOrderDelivery ON SalesOrderLine.SOI_RecordID = SalesOrderDelivery.SOD_SOI_RecordID,
WO.
INNER JOIN Item ON SalesOrderLine.SOI_IMA_RecordID = Item.IMA_RecordID
INNER JOIN WKO wk ON Item.IMA_ItemID = WK.WKO_ItemID
INNER JOIN Customer ON SalesOrder.SOM_CUS_RecordID = Customer.CUS_RecordID
INNER JOIN woo WO ON WO.WOO_WorkOrderID = WK.WKO_WorkOrderID
WHERE wk.WKO_StatusCode = 'Released'
AND WO.WOO_StatusCode IS NULL
AND SalesOrderDelivery.SOD_ShipComplete = 'false'
GROUP BY WK.WKO_WorkOrderID,
Item.IMA_ItemID,
Item.IMA_ItemName,
Customer.CUS_CorpName,
WK.WKO_WorkOrderTypeCode,
wk.WKO_MatlIssueDate,
Item.IMA_ItemTypeCode,
Item.IMA_OnHandQty
I need 1 record returned for each wk.wko_workorderid. There is a field that is not included that I'm not sure how to get. I need to retrieve the woo.woo_workcenterid that corresponds to min(WO.woo_operationseqID)as seqid. I cannot include it in the general query since there are multiple workcenterids in the table and I only want the specific one that is part of the min operation sequence record.
Any help would be appreciated.

SQL Join and integer condition in jointure to make them relative

i already submit my problem but without example it was not clear enough so here is the tables :
Users
id_user / key_user
1 / 123FDADA21312QD
2 / 994GFCS4595433D
Companies
id_company / key_company
1 / 3123123123
2 / 5435345454
Products
id_product / id_company_product / code_product
1 / 1 / iphone
2 / 1 / iBook
3 / 1 / macbook
Tyds
id_tyd / user_tyd / product_tyd
1 / 1 / 1 -- mean that the id_user = 1 made a line for the iphone
sold by the company 1
2 / 1 / 2 -- same : user 1 for the ibook of company 1
Here is my request :
SELECT
products.id_product,
users.id_user,
COALESCE(id_tyd, 'NONE') AS id_tyd
FROM tyds
INNER JOIN users
ON tyds.user_tyd = users.id_user
INNER JOIN products
ON tyds.product_tyd = products.id_product
INNER JOIN companies
ON products.id_company_product = companies.id_company
WHERE users.key_user = '123FDADA21312QD'
AND companies.module_key_company = '3123123123'
AND products.cancelled_product >= 0
AND products.code_product = 'iphone'
That will return
products.id_product = 1
users.id_user = 1
tyds.id_tyd = 1
Perfect. But what i'd like to do is getting the users.id_user EVEN IF there is no records for this user in tyds. Like :
SELECT
products.id_product,
users.id_user,
COALESCE(id_tyd, 'NONE') AS id_tyd
FROM tyds
INNER JOIN users
ON tyds.user_tyd = users.id_user
INNER JOIN products
ON tyds.product_tyd = products.id_product
INNER JOIN companies
ON products.id_company_product = companies.id_company
WHERE users.key_user = '123FDADA21312QD'
AND companies.module_key_company = '3123123123'
AND products.cancelled_product >= 0
AND products.code_product = 'macbook'
I'd like to get :
products.id_product = 3
users.id_user = 1
tyds.id_tyd = NONE
Because at this step, i'm sure that the product i ask exists and the user_key exist. But i'm not sure that there is matching records in tyds and that is what i want to test.
Of course, all the tables are simplify and i'll need more datas but i think this will make my point.
My first move was to put the WHERE condition in the JOIN match but, don't know why, if i put the products.code_product in the products jointure, it give me tyds records even for different id_product...
Thanks a lot for your help !
if that's the case, change the join from INNER JOIN to LEFT JOIN. INNER JOIN, basically returns rows that are present (atleast one match) on all tables being joined, while LEFT JOIN returns rows on the lefthand side even without matching records on the other tables.
Query,
SELECT c.*, d.id_tyd
FROM
(
SELECT a.id_user, b.id_product
FROM users a CROSS JOIN products b
) c
LEFT JOIN tyds d
ON d.user_tyd = c.id_user AND
d.product_tyd = c.id_product
LEFT JOIN products e
ON e.id_product = c.id_product
LEFT JOIN companies f
ON e.id_company_product = f.id_company
LEFT JOIN users g
ON c.id_user = g.id_user
WHERE e.code_product = 'macbook' AND
f.key_company = '3123123123' AND
g.key_user = '123FDADA21312QD'
SQLFiddle Demo

How to use ISNULL in a Query within a query?

My SQL Query below is now Returning the RoomsAvailable field correctly except when theres 0 rooms taken, in which the SQL command subtracts number_of_rooms with NULL and outputs NULL to the Column. I have tried numerous ISNULL variations and found that it doesnt work; anyone know how I should be doing this?
SQL :
SELECT
Hotel_2.hotel_code,
Hotel_2.hotel_country,
Room_type_rates_2.room_type_code,
Room_type_rates_2.number_of_rooms,
Types_2.room_type,
Room_type_rates_2.rates,
Room_type_rates_2.number_of_rooms -
(SELECT
DISTINCT (SELECT
COUNT(dbo.Hotel.hotel_code) AS RoomsTake
FROM
dbo.Hotel
INNER JOIN dbo.Hotel_Reservation
ON dbo.Hotel.hotel_code = dbo.Hotel_Reservation.hotel_code
INNER JOIN dbo.Room_type_rates
ON dbo.Hotel.hotel_code = dbo.Room_type_rates.hotel_code
INNER JOIN dbo.Types
ON dbo.Hotel_Reservation.room_type_code = dbo.Types.room_type_code
AND dbo.Room_type_rates.room_type_code = dbo.Types.room_type_code
WHERE
(dbo.Room_type_rates.room_type_code = Room_type_rates_1.room_type_code)
AND (dbo.Hotel.hotel_code = Hotel_1.hotel_code)
AND (dbo.Hotel_Reservation.checkin_date >= Hotel_Reservation_1.checkin_date)
AND (dbo.Hotel_Reservation.checkout_date <= Hotel_Reservation_1.checkout_date)
) AS RoomsTaken
FROM
dbo.Hotel AS Hotel_1
INNER JOIN dbo.Hotel_Reservation AS Hotel_Reservation_1
ON Hotel_1.hotel_code = Hotel_Reservation_1.hotel_code
INNER JOIN dbo.Room_type_rates AS Room_type_rates_1
ON Hotel_1.hotel_code = Room_type_rates_1.hotel_code
INNER JOIN dbo.Types AS Types_1
ON Hotel_Reservation_1.room_type_code = Types_1.room_type_code
AND Room_type_rates_1.room_type_code = Types_1.room_type_code
WHERE
(Hotel_Reservation_1.checkin_date >= '11/19/2011')
AND (Hotel_Reservation_1.checkout_date <= '12/01/2011')
AND (Hotel_1.hotel_country = 'Adelaide')
AND (Types_1.room_type_code = Types_2.room_type_code)
) AS RoomsAvailable
FROM
dbo.Hotel AS Hotel_2
INNER JOIN dbo.Room_type_rates AS Room_type_rates_2
ON Hotel_2.hotel_code = Room_type_rates_2.hotel_code
INNER JOIN dbo.Types AS Types_2
ON Room_type_rates_2.room_type_code = Types_2.room_type_code
Current Output :
ADL20 Adelaide CPL 6 Couple Suite 514.0000 3
ADL20 Adelaide FYU 3 Family Suite 533.0000 2
ADL20 Adelaide KNG 2 King's Bedroom 556.0000 NULL
Do you mean this?:
...ISNULL(COUNT(dbo.Hotel.*),0)...
Or is the problem that you're getting NULL at all? In that case I would suspect your JOINs may have a problem.
You can wrap an ISNULL around any nested subquery or value.

SQL joins "going up" two tables

I'm trying to create a moderately complex query with joins:
SELECT `history`.`id`,
`parts`.`type_id`,
`serialized_parts`.`serial`,
`history_actions`.`action`,
`history`.`date_added`
FROM `history_actions`, `history`
LEFT OUTER JOIN `parts` ON `parts`.`id` = `history`.`part_id`
LEFT OUTER JOIN `serialized_parts` ON `serialized_parts`.`parts_id` = `history`.`part_id`
WHERE `history_actions`.`id` = `history`.`action_id`
AND `history`.`unit_id` = '1'
ORDER BY `history`.`id` DESC
I'd like to replace `parts`.`type_id` in the SELECT statement with `part_list`.`name` where the relationship I need to enforce between the two tables is `part_list`.`id` = `parts`.`type_id`. Also I have to use joins because in some cases `history`.`part_id` may be NULL which obviously isn't a valid part id. How would I modify the query to do this?
Here is some sample date as requested:
history table:
(source: ianburris.com)
serialized_parts table:
(source: ianburris.com)
parts table:
(source: ianburris.com)
part_list table:
(source: ianburris.com)
And what I want to see is:
id name serial action date_added
4 Battery 567 added 2010-05-19 10:42:51
3 Antenna Board 345 added 2010-05-19 10:42:51
2 Main Board 123 added 2010-05-19 10:42:51
1 NULL NULL created 2010-05-19 10:42:51
This would at least be on the right track...
If you're looking to NOT show any parts with an invalid ID, simply change the LEFT JOINs to INNER JOINs (they will restrict NULL values)
SELECT `history`.`id`
, `parts`.`type_id`
, `part_list`.`name`
, `serialized_parts`.`serial`
, `history_actions`.`action`
, `history`.`date_added`
FROM `history_actions`
INNER JOIN `history` ON `history`.`action_id` = `history_actions`.`id`
LEFT JOIN `parts` ON `parts`.`id` = `history`.`part_id`
LEFT JOIN `serialized_parts` ON `serialized_parts`.`parts_id` = `history`.`part_id`
LEFT JOIN `part_list` ON `part_list`.`id` = `parts`.`type_id`
WHERE `history`.`unit_id` = '1'
ORDER BY `history`.`id` DESC
Boy, these backticks make my eyes hurt.
SELECT
h.id,
p.type_id,
pl.name,
sp.serial,
ha.action,
h.date_added
FROM
history h
INNER JOIN history_actions ha ON ha.id = h.action_id
LEFT JOIN parts p ON p.id = h.part_id
LEFT JOIN serialized_parts sp ON sp.parts_id = h.part_id
LEFT JOIN part_list pl ON pl.id = p.type_id
WHERE
h.unit_id = '1'
ORDER BY
history.id DESC