How to write COALESCE SQL creating multiple columns where rows need to be the same type - multiple-columns

SQL Newbie here. I have tried to make sense of others posts, but I cannot seem to make this work. I apologize in advance for incorrect terminology. I am here to learn from the wisdom of others.
I have a part number that has 3 different 'states'. Each part number has the same core characterset, but has a different prefix for the other two states.
Packaged product = 2-181032
Non-Packaged Product = R-181032
Part number in production = MF-R-181032
I want to be able to place each of the records above into one row, but three columns and such for the remaining part numbers. R- and MF- are only used as the prefixes stated above. Here is what I have, but it does not filter the data into the columns as I like. Filter, meaning take the non-MF and non MF-R records and putting them into their own columns, and removing from the first column. I have removed the 3rd part number from the code because it I get a error of "GDS Exception. 335544800. Too many Contexts of Relation/Procedure/Views. Maximum allowed is 255"
SELECT part.num AS part,
part.description AS description,
uom.code AS uomcode,
COALESCE((SELECT SUM(qtyonhand.qty)
FROM qtyonhand
WHERE qtyonhand.partid = part.id
AND part.num NOT LIKE '[MR]%'
AND qtyonhand.locationgroupid IN ('1')),0) AS Qty,
COALESCE((SELECT SUM(qtynotavailable.qty)
FROM qtynotavailable
WHERE qtynotavailable.partid = part.id
AND part.num NOT LIKE '[MR]%'
AND qtynotavailable.locationgroupid IN ('1')), 0) AS Unavailable,
COALESCE((SELECT SUM(qtycommitted.qty)
FROM qtycommitted
WHERE qtycommitted.partid = part.id
AND part.num NOT LIKE '[MR]%'
AND qtycommitted.locationgroupid IN ('1')), 0) AS QtyCommitted,
COALESCE((SELECT SUM(QtyAllocated.qty)
FROM QtyAllocated
WHERE QtyAllocated.partID = Part.id
AND part.num NOT LIKE '[MR]%'
AND QtyAllocated.locationgroupid IN ('1')), 0) AS Allocated,
COALESCE((SELECT SUM(qtyonorder.qty)
FROM qtyonorder
WHERE qtyonorder.partid = part.id
AND part.num NOT LIKE '[MR]%'
AND qtyonorder.locationgroupid IN ('1')), 0) AS OnOrder,
part.num AS part2,
COALESCE((SELECT SUM(qtyonhand.qty)
FROM qtyonhand
WHERE qtyonhand.partid = part.id
AND part.num LIKE 'R-%'
AND qtyonhand.locationgroupid IN ('1')),0) AS Qty2,
COALESCE((SELECT SUM(qtynotavailable.qty)
FROM qtynotavailable
WHERE qtynotavailable.partid = part.id
AND part.num LIKE 'R-%'
AND qtynotavailable.locationgroupid IN ('1')), 0) AS Unavailable2,
COALESCE((SELECT SUM(qtycommitted.qty)
FROM qtycommitted
WHERE qtycommitted.partid = part.id
AND part.num LIKE 'R-%'
AND qtycommitted.locationgroupid IN ('1')), 0) AS QtyCommitted2,
COALESCE((SELECT SUM(QtyAllocated.qty)
FROM QtyAllocated
WHERE QtyAllocated.partID = Part.id
AND part.num LIKE 'R-%'
AND QtyAllocated.locationgroupid IN ('1')), 0) AS Allocated2,
COALESCE((SELECT SUM(qtyonorder.qty)
FROM qtyonorder
WHERE qtyonorder.partid = part.id
AND part.num LIKE 'R-%'
AND qtyonorder.locationgroupid IN ('1')), 0) AS OnOrder2
FROM part
LEFT JOIN uom ON part.uomid = uom.id
WHERE part.num LIKE '%'
AND part.id != 0
AND part.typeid = 10
AND part.activeflag = 1
ORDER BY part.num
Desired result is:
enter image description here

Related

Mysql-cast and convert in joins is not working

In a MySQL table, they have stored return_time as VARCHAR(20) and return_date as a date field. Now I have to compare this based on the given date and time and produce the result. For example, records save in the time column will be like '10:00 PM', '11:00 PM', '02:00 AM' etc and in the date column like '2021-02-02', '2021-01-02' etc
I combined the return_dateand return_time, and compare it with the given date and time like
SELECT *
FROM `travel_infos` as TravelInfo
WHERE TravelInfo.travel_status = 'Open' AND
cast(concat(TravelInfo.return_date, ' ', STR_TO_DATE(TravelInfo.return_time, '%l:%i %p' )) as datetime) > '2021-03-03 14:03'
It outputs me 231 records. travel_infos table has 700 records.
Then I do the join without considering the return_time column
SELECT Part.*,TravelInfo.*,Category.*,Buttons.*
FROM travel_infos As TravelInfo
LEFT JOIN parts as Part ON Part.id = TravelInfo.part_id_1
LEFT JOIN buttons as Buttons ON Part.button_name_id= Buttons.id
LEFT JOIN categories as Category ON Part.category_id = Category.id
WHERE Part.id != 0 AND TravelInfo.id!=0
AND Part.part_type IN('Charter') AND Part.store_id='1'
AND TravelInfo.travel_status = 'Open'
AND TravelInfo.return_date >= '2021-03-03 14:03'
AND Part.is_delete=0
It outputs me 175 records.
So now I want to join by considering both return_date and return_time. So I tried like
SELECT Part.*,TravelInfo.*,Category.*,Buttons.*
FROM travel_infos As TravelInfo
LEFT JOIN parts as Part ON Part.id = TravelInfo.part_id_1
LEFT JOIN buttons as Buttons ON Part.button_name_id= Buttons.id
LEFT JOIN categories as Category ON Part.category_id = Category.id
WHERE Part.id != 0 AND
TravelInfo.id!=0
AND Part.part_type IN('Charter')
AND Part.store_id='1'
AND TravelInfo.travel_status = 'Open'
AND (cast(concat(TravelInfo.return_date, ' ',
STR_TO_DATE(TravelInfo.return_time, '%l:%i %p' )) as datetime)) >= '2021-03-03 14:03' AND Part.is_delete=0
This outputs me 0 records. What went wrong in the 3rd SQL query? Both 1st and 2nd produce the output.
In my 3rd query, I modified the 2nd query WHERE like in the 1st query.
Can someone help me to solve this thank you.
Convert both dates you are comparing to datetimes in the where clause:
SELECT Part.*,TravelInfo.*,Category.*,Buttons.*
FROM travel_infos As TravelInfo
LEFT JOIN parts as Part ON Part.id = TravelInfo.part_id_1
LEFT JOIN buttons as Buttons ON Part.button_name_id= Buttons.id
LEFT JOIN categories as Category ON Part.category_id = Category.id
WHERE Part.id != 0 AND
TravelInfo.id!=0
AND Part.part_type IN('Charter')
AND Part.store_id='1'
AND TravelInfo.travel_status = 'Open'
AND TravelInfo.return_date >= STR_TO_DATE('2021-03-03', '%Y-%m-%d')
AND cast(TravelInfo.return_time as time) >= cast('14:03:00' as time)
AND Part.is_delete=0

Turn simple query into a count case statement

I have a query that is quite helpful, that I would like help simplifying and turning into a count that I can add to a larger query that I'm working on. I have a scenario that occurs in my data where there are many to one relationships where there shouldn't be. Just to keep it simple, I'd describe it as if ford were describing all of the sedans they sold of a particular model, and in their data base they had more than one occurrence of a 'Red Sedan'. This causes problems for us, and I'd like to product a simple count of that occurrence in a larger query.
I have a query that successfully uncovers all cases of duplicates of 'red sedan' occurring (below)
select p.model, p.mFinish, count(p.productVendorStockNumber) as prodno, b.BrandName
from products p
join brands b on p.brandID = b.brandID
where p.brandid = 299 and p.`status` = 1 and p.model != ''
GROUP BY p.model, p.mFinish
HAVING prodno > 1;
which produces an output something like this (did my best to reproduce it there - sorry)
|Model|Finish| Prod No| BrandName|
|12334|Red | 2 | Santec
What I'd like to do though is have just the count, which in this case is 'prod no' come out in a case statement. I'm sort of a journeymen SQL guy so reducing an entire query into a count is something that is beyond me. I'm not even quite sure what to search for, I tried enclosing the entire query in "Count" and "Sum" on a lark and obviously that didn't work. When someone has a moment can they please provide a little insight into how something like that would be done?
I don't know if this is helpful or not, but the query I'm adding it to is below
select b.brandName, b.BrandCode, SUM(Case When p.IMAP > p.MSRP THEN 1 ELSE NULL END) as 'MAP Greater Than MSRP', COUNT(DISTINCT(p.ProductVendorStockNumber)) as 'Total Products', MAX(dl.createDate) 'Most Recent Data Load', b.BrandStatus, b.datasource as 'Data Source', b.state as 'State', CASE WHEN dl.datanextConf = 1 THEN 'Confirmed' ELSE 'Not Confirmed' END AS 'Data Incoming?'
from products p
left join brands b on p.brandID = b.brandID
left join dataloads dl on b.brandID = dl.brandID
where p.status = 1 and b.brandID = 653
Not sure why, but someone posted an answer and then the answer was deleted. I'm reposting what they provided.
SELECT
b.brandName,
b.BrandCode,
SUM( CASE WHEN p.IMAP > p.MSRP THEN 1 ELSE NULL END ) AS 'MAP Greater Than MSRP',
COUNT( DISTINCT ( p.ProductVendorStockNumber ) ) AS 'Total Products',
ROUND(COUNT( DISTINCT (p.ImageName) )/COUNT( DISTINCT ( p.ProductVendorStockNumber ) ),2) '% with images',
MAX( dl.createDate ) 'Most Recent Data Load',
b.BrandStatus,
b.datasource AS 'Data Source',
b.state AS 'State',
CASE
WHEN dl.datanextConf = 1 THEN
'Confirmed' ELSE 'Not Confirmed'
END AS 'Data Incoming?',
(
SELECT
count( * )
FROM
products p2
WHERE
p2.brandid = p.brandid
AND p2.model = p.model
AND p2.mFinish = p.mFinish
AND p2.`status` = p.`status`
) AS 'Total Duplicate Finishes'
FROM
products p
LEFT JOIN brands b ON p.brandID = b.brandID
LEFT JOIN dataloads dl ON b.brandID = dl.brandID
WHERE
p.STATUS = 1
AND b.brandID = 286

mysql 'as' repated

The 1st piece of code works fine and gives me the results I need.
what I want to do now is to have it return 3 number values on the 'as num'
for 3 different values on the 'as num' for 3 different where on the same column
SELECT COUNT(garage_list.account_id) as num,
garage_list.account_id,
garage_list.tank_id,
player_list.clan,
player_list.nickname,
tank_list.level
FROM garage_list
RIGHT JOIN player_list ON garage_list.account_id = player_list.account_id
RIGHT JOIN tank_list ON garage_list.tank_id = tank_list.tank_id
where tank_list.level='8'
and player_list.clan = 'bad-1'
GROUP BY account_id
above works
need to have a returned value for each of the " where tank_list.level='??' "
SELECT COUNT(garage_list.account_id) as num,
garage_list.account_id,
garage_list.tank_id,
player_list.clan,
player_list.nickname,
tank_list.level
FROM garage_list
RIGHT JOIN player_list ON garage_list.account_id = player_list.account_id
RIGHT JOIN tank_list ON garage_list.tank_id = tank_list.tank_id
where tank_list.level='6' //return a value for this
where tank_list.level='8' //return a value for this
where tank_list.level='10' //return a value for this
and player_list.clan = 'bad-1'
GROUP BY account_id
You need a conditional COUNT using a CASE:
SELECT COUNT(case when tank_list.level='6' then garage_list.account_id end) as num1,
COUNT(case when tank_list.level='8' then garage_list.account_id end) as num2,
COUNT(case when tank_list.level='10' then garage_list.account_id end) as num3,
garage_list.account_id,
garage_list.tank_id,
player_list.clan,
player_list.nickname,
tank_list.level
FROM garage_list
RIGHT JOIN player_list ON garage_list.account_id = player_list.account_id
RIGHT JOIN tank_list ON garage_list.tank_id = tank_list.tank_id
where tank_list.level in ('6','8','10')
and player_list.clan = 'bad-1'
GROUP BY account_id
And you need to check if your Outer Join logic is correct.

How to write if else condition in sql

In the following sql, how can i add if-else like control structure.
SELECT
tblcabbooking.id AS id,
concat(tblcabstatus.`status`,' ',
ifnull(concat("(INR",tblbookingcharges.totalbill,")"),'')) AS `status`,
tblcomplaint.id AS com_id,
tblcomplaint.statusid AS com_status,
tblcabbooking.csr_id AS emp,
concat(tblcabbooking.dropaddress,tblcabbooking.droparea) AS drop_area,
tblbookingcharges.totalbill,
tblcabbooking.booking_reference AS ref,
tblmasterpackage.master_package AS booking_type,
concat(tblcabbooking.pickupdate," ",tblcabbooking.pickuptime) AS ordertime,
concat(tblclient.clientname," ",tblappid.`type`) AS partner,
concat(tblcablistmgmt.NAME,', ',tbldriver.firstname,"(",tbldriver.contactno,")") AS vehicle,
concat(tbluserinfo.firstname,"(",tbluserinfo.mobno,")") AS clientname,
concat(tbldriver.firstname," ",tbldriver.contactno) AS driver_name,
tblcabbooking.mobileno AS mob_no,
tbluserinfo.uid AS client_id,
tbldriver.uid AS driver_id,
concat(tblcabbooking.pickupaddress,' ',tblcabbooking.pickuparea) AS departure,
tbldriver.vehicleregistrationno AS reg
FROM tblcabbooking
JOIN tblcabstatus
ON tblcabbooking.`status`=tblcabstatus.`status_id`
JOIN tbluserinfo
ON tbluserinfo.uid=tblcabbooking.clientid
JOIN tblmasterpackage
ON tblcabbooking.bookingtype=tblmasterpackage.package_id
LEFT JOIN tbldriver
ON tblcabbooking.pickup=tbldriver.uid
LEFT JOIN tblcablistmgmt
ON tbldriver.typeofvehicle=tblcablistmgmt.id
JOIN tblappid
ON tblappid.id=tblcabbooking.partner
JOIN tblclient
ON tblappid.clientid=tblclient.id
LEFT JOIN tblbookingcharges
ON tblcabbooking.id=tblbookingcharges.bookingid
LEFT JOIN tblcomplaint
ON tblcabbooking.id=tblcomplaint.bookingid
WHERE tblcabbooking.bookingdate >= fromdate
AND tblcabbooking.bookingdate <= todate
AND tblcabbooking.mobileno=ifnull(callerid,tblcabbooking.mobileno)
AND tblcabbooking.booking_reference=ifnull(book_ref, tblcabbooking.booking_reference)
AND tbldriver.vehicleregistrationno=ifnull(vehicle_number, tbldriver.vehicleregistrationno)
AND tbldriver.firstname=ifnull(vehicle_driver, tbldriver.firstname)IF partnertype LIKE 'Android Booking' then
AND
tblcabbooking.devicetype='ANDROID'
ELSE
IF partnertype LIKE 'Web Booking' then
AND
tblcabbooking.devicetype='WEB'
ELSE
IF partnertype LIKE 'Call Center Booking' then
AND
tblcabbooking.devicetype='0'
ELSE
and
partnertype=tblcabbooking.devicetype
END
IF ORDER BY tblcabbooking.id DESC ;
NO, you can't use IF .. ELSE construct in normal ANSI SQL query, but you can rewrite it using CASE statement like
WHERE tblcabbooking.devicetype =
CASE WHEN partnertype LIKE 'Android Booking'
THEN 'ANDROID' ELSE 'Web Booking'

SQL Query Help - Joining Multiple Columns Based On Condition [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
SQL query help - have two where conditons in join condition
I have the following tables with the columns as below. I have mentioned what I need from this. I already posted a link in here SQL query help - have two where conditons in join condition with what I have been trying but cannot get this through. Once again positing it plainly with what I need:
Book
BookId, BookName
Desk
DeskId, BookId ,DeskName
CounterParty
CPId, CpName
Trade
TradeId, Buyer, Seller
This is how the Buyer and Seller data would be :
Buyer Seller
B3232 B323
C32 B222
B323 C323
Based on the starting character B or C in these two columns, I need to join Book or CP table to check the ids.
I need **t.TradingDeskName, b.BookName, c.CpName, t.Buyer, t.Seller.**
Any help is very much appreciated.
Thanks,
mani
p.s : I am trying to get this done through SQL or Linq to Sql.
The recent query but have more to fix :
SELECT DISTINCT desk.Name as TradingDeskName, b.Name as Book, t.Seller, t.Buyer, c.PartyName, FROM TradingDesk AS desk
RIGHT JOIN Book as b
ON b.TradingDeskId = d.Id
RIGHT JOIN Trade as t
ON LEFT(t.Buyer, 1) = 'B' AND SUBSTRING(t.Buyer, 2, len(t.Buyer)) = b.Id
LEFT JOIN Book as b1
ON LEFT(t.Seller, 1) = 'B' AND SUBSTRING(t.Seller, 2, len(t.Seller)) = b1.Id
LEFT JOIN CounterParty as c
ON LEFT(t.Buyer, 1) = 'C' AND SUBSTRING(t.Buyer, 2, len(t.Buyer)) = c.PartyId
LEFT JOIN CounterParty as c1
ON LEFT(t.Seller, 1) = 'C' AND SUBSTRING(t.Seller, 2, len(t.Seller)) = c1.PartyId
As I mentioned I need :
Desk.Name - B.Name - T.Seller - T.Buyer- C.PartyName
The C.PartyName will have the value if T.Seller or T.Buyer value is starting with 'C' (from CounterParty Table) else will be null.
With the above query, I have null values coming in Desk.Name, B.Name and the logic of gettig C.PartyName is also not working.
There are a couple ways I could think of for achieving the desired results but because first things should come first, I'd suggest to modify the DB design if it is at all possible.
So, here are the 2 queries that I could work out:
Query 1
SELECT `t`.*,
(CASE
WHEN LEFT(`t`.`Buyer`, 1) = 'B' THEN
(SELECT `b`.`BookName`
FROM `Book` `b`
WHERE `b`.`BookId` = SUBSTRING(`t`.`Buyer`, 2))
ELSE (SELECT `c`.`CPName`
FROM `CounterParty` `c`
WHERE `c`.`CPId` = SUBSTRING(`t`.`Buyer`, 2))
END) AS `buyer_name`,
(CASE
WHEN LEFT(`t`.`Seller`, 1) = 'B' THEN
(SELECT `b`.`BookName`
FROM `Book` `b`
WHERE `b`.`BookId` = SUBSTRING(`t`.`Seller`, 2))
ELSE (SELECT `c`.`CPName`
FROM `CounterParty` `c`
WHERE `c`.`CPId` = SUBSTRING(`t`.`Seller`, 2))
END) AS `seller_name`
FROM `Trade` `t`
Query 2
SELECT *
FROM `Trade` `t`
LEFT JOIN `Book` `b` ON LEFT(`t`.`Buyer`, 1) = 'B' AND SUBSTRING(`t`.`Buyer`, 2) = `b`.`BookId`
LEFT JOIN `Book` `b1` ON LEFT(`t`.`Seller`, 1) = 'B' AND SUBSTRING(`t`.`Seller`, 2) = `b1`.`BookId`
LEFT JOIN `CounterParty` `c` ON LEFT(`t`.`Buyer`, 1) = 'C' AND SUBSTRING(`t`.`Buyer`, 2) = `c`.`CPId`
LEFT JOIN `CounterParty` `c1` ON LEFT(`t`.`Seller`, 1) = 'C' AND SUBSTRING(`t`.`Seller`, 2) = `c1`.`CPId`;
Both the above queries return same results but in different formats. Please try and see which one works best for you.
Also, it isn't very clear from your question where does the table Desk fit in and what relations does it hold with other tables. Please feel free to add respective columns you'll need from Desk.
Please note that the suggested queries are in MySQL. It is not very clear what system are you running - you've mentioned in your post that you are trying using SQL or Linq SQL and in the tags you've mentioned everything + MySQL.
You could do it something like this (untested):
select
t.Buyer,
t.Seller,
case when t.Buyer like 'B%' THEN (select BookName from Book where BookId = t.Buyer)
ELSE (select CpName from Counterparty where CPId = t.Buyer)
end BuyerName,
case when t.Buyer like 'B%' THEN (select DeskName from Desk where BookId = t.Buyer)
ELSE NULL
end BuyerDeskName,
case when t.Seller like 'B%' THEN (select BookName from Book where BookId = t.Seller)
ELSE (select CpName from Counterparty where CPId = t.Seller)
end SellerName,
case when t.Seller like 'B%' THEN (select DeskName from Desk where BookId = t.Seller)
ELSE NULL
end SellerDeskName,
from
Trade t
The problem you have is that, since the table you want to join to is data driven, you can't specify it in the FROM clause..