Update table if all results from multiple UNION queries is 0 - mysql

I have 2 tables with stock from two different sellers.
If I can not source the product from any of these two sellers then I would like to set a value in another table to '0'.
First of all I am getting some required values from the two seller stock tables combined with a UNION
(SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'Stock available' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_dm` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '1' AND B.`product_id` > '0'
UNION
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'In Stock' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_m` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '2' AND B.`product_id` > '0') t1
If I get a result like below where in_stock = 0 for both sellers then I would like to update another field with 0
id product_id internal_id in_stock
1 123 5555 0
1 123 4567 0
If I can source the product from one (like below) or both sellers then I don't want to do anything.
id product_id internal_id in_stock
1 123 5555 0
1 123 4567 1
Basically how can I check if all results for a product_id are 'in_stock = 0' and based on that do an update of another table.
Thank you

There are easier ways to do this if the tables can be joined, but You could get the max in_stock number and knowing that if it's over 0 you could do it with a CTE like this (I am not able to test this in mysql so it may need some syntax correction)
WITH CTE (in_stock) AS (
SELECT MAX(in_stock) from (
(SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'Stock available' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_dm` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '1' AND B.`product_id` > '0'
UNION
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'In Stock' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_m` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '2' AND B.`product_id` > '0') t1 ))
UPDATE some_table SET some_column = 0
where CTE.in_stock < 1

I used nested queries and a variable to meet your criteria.
See example DDL in this link:https://www.db-fiddle.com/f/8jUMnbEFpGWA4fmmP67yw9/0 I think this meets your requirements.
Here is my Query, with comments:
#check initial another table values
select * from another_table;
#check the given resultset
#there are 3 pairs,
#2 of which meet the condition for not updating
#1 of the pairs meets the condition for doing the requested update
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'Stock available' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_dm` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '1' AND B.`product_id` > '0'
UNION
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'In Stock' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_m` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '2' AND B.`product_id` > '0';
#the requested update statement
set #chk1 := 0;
update another_table
set crab_people = 0
where product_id in
#this nested query will return all product_id
#that fits the criteria to update another_table
(select product_id_not_in_stock from
(select
case
when product_id = #chk1 and in_stock = 0 then #chk1
when product_id != #chk1 and in_stock = 0 then #chk1 := product_id
end as product_id_not_in_stock
from
(SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'Stock available' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_dm` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '1' AND B.`product_id` > '0'
UNION
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'In Stock' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_m` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '2' AND B.`product_id` > '0') as t1
order by product_id, in_stock DESC, internal_id) as t2
where product_id_not_in_stock is not null
group by product_id_not_in_stock
having count(product_id_not_in_stock) > 1);
#confirm the changes went though
#expect crab_people from another_table to be updated
#where the product id is not in stock from both tables: pricing_dm and pricing_m
select * from another_table;

Related

Grouping different column into one row

How to make one row in different rows and column
SELECT
internal_id, store_id, user_id, shift_info,
DATE(log_datetime) dates,
(case when log_action = '0' then TIME(log_datetime) end) as time_in,
(case when log_action = '0' then CONCAT(log_lat, ",", log_lng) end) as loc_in,
(case when log_action = '1' then TIME(log_datetime) end) as time_out,
(case when log_action = '1' then CONCAT(log_lat, ",", log_lng) end) as loc_out
FROM
attendance_store_user
WHERE
user_id = "A4CBD64F-D21C-5612-CCF5-497892B62E76"
i want result like this :
You could try using a join of the same table filter for null time_out and time_in
select a.dates, a.store_id, a,time_in, b.time_out
FROM attendance_store_user a
INNER JOIN attendance_store_user b on a.dates = b.dates
and a.user_id = b.user_id
and a.time_out is null
and b.time_in is null
WHERE a.user_id = "A4CBD64F-D21C-5612-CCF5-497892B62E76"

Combining all data with a unique ID - MySQL

I have this data that I got from my current query.
What I want to do is combine and make it a single row where the type is Senior, the cashamount and Tenderamount are the same as well.
This is my desired result:
I'm getting my data from this table:
Here's my query:
SELECT a.DATE as `DATE`, a.employee as `EMPLOYEE`, a.TYPEID, a.NAME as
`NAME`, (select (case when a.typeid = 1 then a.amount else NULL end)) as
`CASHAMOUNT`,
(select (case when a.typeid <> 1 then a.amount else NULL end)) as
`TENDERAMOUNT`, (select gndtndr.IDENT from gndtndr where gndtndr.TYPE = 12
and `gndtndr`.`CHECK`= a.CHECK and gndtndr.DATE = a.DATE) as `ID`,
from gndtndr a
where STR_TO_DATE(a.DATE, '%m/%d/%Y') BETWEEN '20170901' AND '20170901'
order by STR_TO_DATE(a.DATE, '%m/%d/%Y')
My MySQL is a bit rusty, but give this a try!
SELECT a.Date, a.Employee, a.Name, a.ID, SUM(b.Amount) AS CashAmount,
SUM(c.Amount) AS TenderAmount FROM
(SELECT DISTINCT Date, Employee, Name, ID FROM gndtndr WHERE Type = 12) AS a
LEFT JOIN gndtndr AS b
ON a.ID = b.ID AND b.TypeID = 1
LEFT JOIN gndtdr AS c
ON a.ID = c.ID and c.TypeID <> 1
GROUP BY a.Date, a.Employee, a.Name, a.ID
I've figured it out :) I just have to define the type conditions in my where clause where the type is 1(for cash).
SELECT a.DATE as `DATE`, a.employee as `EMPLOYEE`, a.TYPEID, a.NAME as
`NAME`, (select sum(gndtndr.amount) from gndtndr where gndtndr.typeid = 1
and gndtndr.`CHECK` = a.`CHECK` and gndtndr.DATE = a.DATE) as `CASHAMOUNT`,
(select (case when a.typeid <> 1 then a.amount else NULL end)) as
`TENDERAMOUNT`, (select gndtndr.IDENT from gndtndr where gndtndr.TYPE = 12
and `gndtndr`.`CHECK`= a.CHECK and gndtndr.DATE = a.DATE) as `ID` from
gndtndr a
where a.TYPEID <> 1 and STR_TO_DATE(a.DATE, '%m/%d/%Y') BETWEEN '20170901'
AND '20170901' order by STR_TO_DATE(a.DATE, '%m/%d/%Y')

CASE statement in SQL giving not proper values

I am having abnormal values when I run this part in my sql code. SQL syntax wise, everything is okay with this?
select
COUNT(CASE WHEN bt.idBillingStatus = 2
THEN 1
ELSE NULL END) AS successfulbillinghits,
SUM(CASE WHEN bt.idBillingStatus = 2
THEN price
ELSE 0.0 END)
AS old_revenue
from table
Overall Query is this. The result of successfulbillinghits should be equal to timesbilled
SELECT
cs.idCustomerSubscription,
cs.msisdn,
pro.name AS promoterName,
c.name AS ClubName,
c.idClub AS ClubID,
o.name AS operatorName,
o.idOperator AS OperatorID,
co.name AS country,
-- cu.customerSince AS CustomerSince,
cs.subscribeddate AS subscribeddate,
-- cs.subscriptionNotificationSent AS SubNotificationSent,
-- cs.eventId AS EventId,
cs.unsubscribeddate AS unsubscribeddate,
cs.firstBillingDate AS FirstBillingDate,
cs.lastBilledDate As LastBilledDate,
cs.lastAttemptDate AS LastAttemptDate,
-- smp.code AS packageName,
-- o.mfactor AS mmfactor,
-- cs.idSubscriptionSource AS SubscriptionChannel,
-- cs.idUnsubscribeSource AS UnsubscriptionChannel,
-- DATE(bt.creationDate) AS BillingCreationDate,
-- bt.price AS pricePerBilling,
-- cs.lastRetryDate As LastRetryDate,
-- cs.lastRenewalDate AS LastRenewalDate,
-- cs.isActive AS ActiveStatus,
-- COUNT(bt.idBillingTransaction) AS BillingAttempts,
curr.idcurreny_symbol AS CurrencyID,
curr.symbol AS currency,
date(bt.creationDate) AS BillingDate,
cs.lastBilledAmount As LastBilledAmount,
cs.timesbilled,
price,
-- sum(price),
-- revenueShareAmountLocal,
-- o.mfactor,
-- count(IFF (bt.idBillingStatus = 2,1,0)) as otherversion,
count(CASE WHEN bt.idBillingStatus = 2
THEN 1
ELSE 0 END) AS successfulbillinghits,
SUM(CASE WHEN bt.idBillingStatus = 2
THEN price
ELSE 0.0 END)
AS old_revenue
FROM
customersubscription cs
LEFT JOIN
billing_transaction bt
ON CONVERT(cs.msisdn USING latin1) = bt.msisdn
AND cs.idClub = bt.idClub
AND bt.creationDate BETWEEN cs.SubscribedDate AND COALESCE(cs.UnsubscribedDate, now())
INNER JOIN customer cu ON (cs.idCustomer = cu.idcustomer)
INNER JOIN operator o ON (o.idoperator = cu.idoperator)
INNER JOIN country co ON (co.`idCountry` = o.idCountry)
INNER JOIN curreny_symbol curr ON (curr.idcurreny_symbol = co.idCurrencySymbol)
LEFT JOIN Promoter pro ON cs.idPromoter = pro.id
INNER JOIN club_operator_relationships cor ON cor.clubId = cs.idClub
INNER JOIN club c ON c.idClub = cs.idClub
-- INNER JOIN operator op ON op.idOperator = cu.idOperator
WHERE
-- (cs.timesbilled > 0 and cs.subscribeddate < '2016-09-01 00:00:00' )
cs.subscribeddate between '2017-04-20 00:00:00' and '2017-04-21 00:00:00'
AND cs.idClub IN (39)
GROUP BY idCustomerSubscription, ClubName, operatorName, promoterName
Successfulbillinghits is much greater than timesbilled in the result
Instead of COUNTuse SUM, as count counts blanks or nulls also
select
SUM(CASE WHEN bt.idBillingStatus = 2
THEN 1
ELSE 0 END) AS successfulbillinghits,
SUM(CASE WHEN bt.idBillingStatus = 2
THEN price
ELSE 0.0 END)
AS old_revenue
from table
Instead of using CASE, you can use WHERE clause with these aggregate functions, e.g.:
SELECT COUNT(*) as `successfulbillinghits`, SUM(price) as `old_revenue`
FROM table bt
WHERE bt.idBillingStatus = 2;

my mysql SELECT case can't return 3 columns

I'm trying to return 3 columns with the query below. the current query works fine.
SELECT cat, COUNT(*) as count FROM
(SELECT case WHEN `cat_type` = 'PREMIUM' then '1'
WHEN `cat_type` = 'NOT PREMIUM' then '2'
WHEN `cat_type` = 'GOLD' then '3'
WHEN `cat_type` = 'EXECUTIVE' then '4'
WHEN `cat_type` = 'NOT PROVIDED' then '-1'
else '-2'
end AS cat FROM `ab` AS s
JOIN `make` AS m
WHERE s.make_code = m.make_code
) AS someRandomAliasHere
GROUP BY cat
ORDER BY CAST(cat AS UNSIGNED) ASC
when i try and return another column cat_type i get an error
SELECT cat, cat_type, COUNT(*) as count FROM ....
The error i get is
#1054 - Unknown column 'cat_type' in 'field list'
but cat_type does exist in my ab table. any idea what i'm missing? Thanks
Your cat_type exists in ab table.
But your ab table does not exists in your main select.
It only exists within the sub query which returns someRandomAliasHere to you.
So you should likely select cat_type from the same select as you select your cases.
Then you should have access to it, but it would then likely mess with your group by / count.
You'll properly need a more advanced query for what you're after.
You need to include cat_type in the subquery. I would recommend:
SELECT cat, cat_type, COUNT(*) as count
FROM (SELECT (case WHEN `cat_type` = 'PREMIUM' then 1
WHEN `cat_type` = 'NOT PREMIUM' then 2
WHEN `cat_type` = 'GOLD' then 3
WHEN `cat_type` = 'EXECUTIVE' then 4
WHEN `cat_type` = 'NOT PROVIDED' then -1
else -2
end) AS cat, *
FROM `ab` AS s JOIN
`make` AS m
USING (make_code)
) AS someRandomAliasHere
GROUP BY cat, cat_type
ORDER BY abs(cat) asc
Note the following:
Added * to the subquery to capture all the columns.
Changed the join syntax. Not only are explicit joins better but the using clause allows the use of * without having to worry about duplicate names among the joined column.
Removed the single quotes from the constant values for cat. You are treating these as numbers in the order by, so use numbers for the values.
Changed the order by to abs() rather than casting to unsigned. However, do you really want unsigned here?
You're not selecting cat_type into someRandomAliasHere, hence it's not available to your main select. This should fix it:
SELECT cat, cat_type, COUNT(*) as count FROM
(SELECT case WHEN `cat_type` = 'PREMIUM' then '1'
WHEN `cat_type` = 'NOT PREMIUM' then '2'
WHEN `cat_type` = 'GOLD' then '3'
WHEN `cat_type` = 'EXECUTIVE' then '4'
WHEN `cat_type` = 'NOT PROVIDED' then '-1'
else '-2'
end AS cat, cat_type FROM `ab` AS s
JOIN `make` AS m
WHERE s.make_code = m.make_code
) AS someRandomAliasHere
GROUP BY cat, cat_type
ORDER BY CAST(cat AS UNSIGNED) ASC
You needed to include the column in subquery first and then reference that using the table.col
Try below
SELECT someRandomAliasHere.cat_type, cat, COUNT(*) as count FROM
(SELECT cat_type, case WHEN `cat_type` = 'PREMIUM' then '1'
WHEN `cat_type` = 'NOT PREMIUM' then '2'
WHEN `cat_type` = 'GOLD' then '3'
WHEN `cat_type` = 'EXECUTIVE' then '4'
WHEN `cat_type` = 'NOT PROVIDED' then '-1'
else '-2'
end AS cat FROM `ab` AS s
JOIN `make` AS m
WHERE s.make_code = m.make_code
) AS someRandomAliasHere
GROUP BY cat
ORDER BY CAST(cat AS UNSIGNED) ASC
You need to also select the column cat_type, so that someRandomAliasHere owns the column.
SELECT cat, cat_type, COUNT(*) as count FROM
(SELECT case WHEN `cat_type` = 'PREMIUM' then '1'
WHEN `cat_type` = 'NOT PREMIUM' then '2'
WHEN `cat_type` = 'GOLD' then '3'
WHEN `cat_type` = 'EXECUTIVE' then '4'
WHEN `cat_type` = 'NOT PROVIDED' then '-1'
else '-2'
end AS cat, cat_type FROM `ab` AS s
JOIN `make` AS m
WHERE s.make_code = m.make_code
) AS someRandomAliasHere
GROUP BY cat, cat_type
ORDER BY CAST(cat AS UNSIGNED) ASC
Dont forget to add cat_type in GROUP BY too.

MySQL - join same table twice

I have a table called 'booking'
> id status
1 P
2 P
and another called 'call'
id calldate type booking
1 01/01/2012 DEL 1
2 01/02/2012 COL 1
3 01/03/2012 DEL 2
4 31/12/2019 COL 999
I want to list each record in 'bookings' ONCE, showing associated records from 'call' as another column like this:
bookingId deliverydate collectiondate
1 01/01/2012 01/02/2012
2 01/03/2012 null
I've tried:
select `b`.`bookingid` AS `bookingid`,
`del`.`calldate` AS `Delivery`,
`col`.`calldate` AS `Collection`
from `booking` `b`
left join `call` `del` on `b`.`bookingid` = `del`.`booking`
left join `call` `col` on `b`.`bookingid` = `col`.`booking`
where ((`del`.`type` = 'DEL') OR (`col`.`type` = 'COL') and (`b`.`status` = 'P'));
but I get bookingid 1 listed 3 times. Can someone please fix my joins?
I think you want to move your types into the join conditions:
select `b`.`bookingid` AS `bookingid`,
`del`.`calldate` AS `Delivery`,
`col`.`calldate` AS `Collection`
from `booking` `b`
left join `call` `del` on `b`.`bookingid` = `del`.`booking` AND `del`.`type` = 'DEL'
left join `call` `col` on `b`.`bookingid` = `col`.`booking` AND `col`.`type` = 'COL'
where `b`.`status` = 'P';
You don't need to join the same table twice, you could use this:
SELECT
`call`.booking,
max(case when type='DEL' then calldate end) as deliverydate,
max(case when type='COL' then calldate end) as collectiondate
FROM
booking inner join `call`
on booking.id=`call`.booking
WHERE
booking.status='P'
GROUP BY `call`.booking