MySQL pivote style query - mysql

I'm trying to create a mysql pivote style query for a google column chart. I would like the 'debit' data to appear under the 'transDesc' description but it always displays as 0. Im fairly new to this platform so could anyone tell me if I'm on the right track?
SELECT
view_monthly_chart.pay_month, view_monthly_chart.transDesc AS Transaction,
IF(view_monthly_chart.transDesc = 'Bills', `debit`, 0) AS bills,
IF(view_monthly_chart.transDesc = 'Misc', `debit`, 0) AS misc,
IF(view_monthly_chart.transDesc = 'Inc', `debit`, 0) AS inc,
IF(view_monthly_chart.transDesc = 'Bank Trans', `debit`, 0) AS bank_trans
FROM view_monthly_chart
GROUP BY view_monthly_chart.pay_month, view_monthly_chart.transDesc
ORDER BY view_monthly_chart.pay_id DESC
The query is based on a view:
select `t1`.`pay_id` AS `pay_id`,`t3`.`pay_month` AS `pay_month`,`t2`.`Desc` AS `transDesc`,floor(sum(`t1`.`debit`)) AS `debit`
from ((`transactions`.`tbltransaction` `t1`
left join `transactions`.`tbltransid` `t2`
on((`t1`.`trans_id` = `t2`.`id`)))
left join `transactions`.`tblpayid` `t3`
on((`t1`.`pay_id` = `t3`.`pay_id`)))
where (`t2`.`Desc` is not null)
group by `t1`.`pay_id`,`t3`.`pay_month`,`t2`.`Desc`
order by `t1`.`pay_id` desc limit 24

The ANSI SQL way to do control structures in a SELECT-statement is using CASE WHEN … THEN … ELSE … END
So something along the lines of:
SELECT
view_monthly_chart.pay_month, view_monthly_chart.transDesc AS Transaction,
CASE WHEN view_monthly_chart.transDesc = 'Bills' THEN debit ELSE 0 END AS bills,
CASE WHEN view_monthly_chart.transDesc = 'Misc' THEN debit ELSE 0 ENDAS misc,
CASE WHEN view_monthly_chart.transDesc = 'Inc' THEN debit ELSE 0 END AS inc,
CASE WHEN view_monthly_chart.transDesc = 'Bank Trans' THEN debit ELSE 0 END AS bank_trans
FROM view_monthly_chart
GROUP BY view_monthly_chart.pay_month, view_monthly_chart.transDesc
ORDER BY view_monthly_chart.pay_id DESC

Related

MySQL - Slow Query when adding multiple derived tables - Optimization

For my query, the two derived tables at the bottom are causing a crazy slow up for this query. The query, as is, takes about 45-55 seconds to execute.. NOW, when i remove just one of those derived tables (it does not matter which one) the query goes down to 0.1 - 0.3 seconds. My questions; Is there an issue with having multiple derived tables? Is there a better way to execute this? My indexes all seem to be correct, I will also include the explain from this query.
select t.name as team, u.name as "REP NAME",
count(distinct activity.id) as "TOTAL VISITS",
count(distinct activity.account_id) as "UNIQUE VISITS",
count(distinct placement.id) as "COMMITMENTS ADDED",
CASE WHEN
count(distinct activity.account_id) = 0 THEN (count(distinct
placement.id) / 1)
else (cast(count(distinct placement.id) as decimal(10,2)) /
cast(count(distinct activity.account_id) as decimal(10,2)))
end as "UNIQUE VISIT TO COMMITMENT %",
case when o.mode='basic' then count(distinct placement.id) else
count(distinct(case when placement.commitmentstatus='fullfilled'
then placement.id else 0 end))
end as "COMMITMENTS FULFILLED",
case when o.mode='basic' then 1 else
(CASE WHEN
count(distinct placement.id) = 0 THEN (count(distinct(case when
placement.commitmentstatus='fullfilled' then placement.id else 0
end)) / 1)
else (cast(count(distinct(case when
placement.commitmentstatus='fullfilled' then placement.id else 0
end)) as decimal(10,2)) / cast(count(distinct placement.id) as
decimal(10,2)))
end) end as "COMMITMENT TO FULFILLMENT %"
from lpmysqldb.users u
left join lpmysqldb.teams t on t.team_id=u.team_id
left join lpmysqldb.organizations o on o.id=t.org_id
left join (select * from lpmysqldb.activity where
org_id='555b918ae4b07b6ac5050852' and completed_at>='2018-05-01' and
completed_at<='2018-06-01' and tag='visit' and accountname is not
null and (status='active' or status='true' or status='1')) as
activity on activity.user_id=u.id
left join (select * from lpmysqldb.placements where
orgid='555b918ae4b07b6ac5050852' and placementdate>='2018-05-01' and
placementdate<='2018-06-01' and (status IN ('1','active','true') or
status is null)) as placement on placement.userid=u.id
where u.org_id='555b918ae4b07b6ac5050852'
and (u.status='active' or u.status='true' or u.status='1')
and istestuser!='1'
group by u.org_id, t.name, u.id, u.name, o.mode
order by count(distinct activity.id) desc
Thank you for assistance!
I have edited below with changing the two bottom joins from joining on subqueries to joining on the table directly. Still yielding the same result.
This is a SLIGHTLY restructured query of your same. Might be simplified as the last two subqueries are all pre-aggregated for your respective counts and count distincts so you can use those column names directly instead of showing all the count( distinct ) embedded throughout the query.
I also tried to simplify the division by multiplying a given count by 1.00 to force decimal-based precision as result.
select
t.name as team,
u.name as "REP NAME",
Activity.DistIdCnt as "TOTAL VISITS",
Activity.UniqAccountCnt as "UNIQUE VISITS",
Placement.DistIdCnt as "COMMITMENTS ADDED",
Placement.DistIdCnt /
CASE WHEN Activity.UniqAccountCnt = 0
THEN 1.00
ELSE Activity.UniqAccountCnt * 1.00
end as "UNIQUE VISIT TO COMMITMENT %",
case when o.mode = 'basic'
then Placement.DistIdCnt
else Placement.DistFulfillCnt
end as "COMMITMENTS FULFILLED",
case when o.mode = 'basic'
then 1
else ( Placement.DistFulfillCnt /
CASE when Placement.DistIdCnt = 0
then 1.00
ELSE Placement.DistIdCnt * 1.00
END TRANSACTION )
END as "COMMITMENT TO FULFILLMENT %"
from
lpmysqldb.users u
left join lpmysqldb.teams t
on u.team_id = t.team_id
left join lpmysqldb.organizations o
on t.org_id = o.id
left join
( select
user_id,
count(*) as AllRecs,
count( distinct id ) DistIdCnt,
count( distinct account_id) as UniqAccountCnt
from
lpmysqldb.activity
where
org_id = '555b918ae4b07b6ac5050852'
and completed_at>='2018-05-01'
and completed_at<='2018-06-01'
and tag='visit'
and accountname is not null
and status IN ( '1', 'active', 'true')
group by
user_id ) activity
on u.id = activity.user_id
left join
( select
userid,
count(*) AllRecs,
count(distinct id) as DistIdCnt,
count(distinct( case when commitmentstatus = 'fullfilled'
then id
else 0 end )) DistFulfillCnt
from
lpmysqldb.placements
where
orgid = '555b918ae4b07b6ac5050852'
and placementdate >= '2018-05-01'
and placementdate <= '2018-06-01'
and ( status is null OR status IN ('1','active','true')
group by
userid ) as placement
on u.id = placement.userid
where
u.org_id = '555b918ae4b07b6ac5050852'
and u.status IN ( 'active', 'true', '1')
and istestuser != '1'
group by
u.org_id,
t.name,
u.id,
u.name,
o.mode
order by
activity.DistIdCnt desc
FINALLY, your inner queries are querying for ALL users. If you have a large count of users that are NOT active, you MIGHT exclude those users from each inner query by adding those join/criteria there too such as...
( ...
from
lpmysqldb.placements
JOIN lpmysqldb.users u2
on placements.userid = u2.id
and u2.status IN ( 'active', 'true', '1')
and u2.istestuser != '1'
where … ) as placement

SQL query to DQL

I have a big query and I want to add a subquery to get the availability of accommodation-rooms.
This is the SQL subquery:
,(SELECT (CASE WHEN count(_days) > 0 THEN 'yes' ELSE 'No' END) as available
FROM
(
SELECT count(rtd.room_type_id) as _days
FROM room_type_day as rtd
WHERE rtd.date IN ('2018-06-20', '2018-06-21', '2018-06-22')
GROUP BY rtd.room_type_id
HAVING COUNT(rtd.room_type_id) = 3
) as sub) as availability
Can anyone tell me how to convert this SQL in DQL?
Thak you
EDIT
I try with this changes but the response is null every time:
,(SELECT (CASE WHEN count(rtd.roomType) > 0 THEN 'yes' ELSE 'no' END)
FROM AppBundle:RoomTypeDayCancelationConditionAccommodation as RTDCCA2
LEFT JOIN RTDCCA2.roomTypeDay as rtd
WHERE rtd.date IN ('2018-06-20', '2018-06-21', '2018-06-22')
GROUP BY rtd.roomType
HAVING COUNT(rtd.roomType) = 3
) as disponible

Getting repetition of same values multiple time while combining two queries

I write two queries in mysql workbench at the time of executing the hole query i am getting the same value. what should i do?
This is my query bellow
Select *
from
(
(select division.name,
date(meter_data.reading_date),
sum(meter_data.meter_delta) 'Gas Consumption (m3)'
from meter, meter_data, division
where meter.meter_id = meter_data.meter_id
and meter.division_id = division.division_id
and Date(meter_data.reading_date) between '2018-04-01' and '2018-05-03'
group by date(meter_data.reading_date)
) as table1,
(Select Date(receipt.receipt_date),
sum(case receipt_item.item_name
when 'Gas' then receipt_item.item_amount else 0
end) 'Gas Purchase'
from receipt_item, receipt
where receipt.receipt_id = receipt_item.receipt_id
and Date(receipt.receipt_date) between '2018-04-01' and '2018-05-03'
group by Date(receipt.receipt_date)
) as table2
);
while executing the queries separately each query returns the exact 33rows but combinedly it returns 1089 rwos
for example i am getting this here all the repetition of same data
but need to show like that (this one is demo image)
I have some problem with my queries the queries should like that beloow
Select *
from
(
(select division.name,
date(meter_data.reading_date) AS reading_date,
sum(meter_data.meter_delta) 'Gas Consumption (m3)'
from meter, meter_data, division
where meter.meter_id = meter_data.meter_id
and meter.division_id = division.division_id
and Date(meter_data.reading_date) between '2018-04-01' and '2018-05-03'
group by date(meter_data.reading_date)
) as table1,
(Select Date(receipt.receipt_date) AS receipt_date,
sum(case receipt_item.item_name
when 'Gas' then receipt_item.item_amount else 0
end) 'Gas Purchase'
from receipt_item, receipt
where receipt.receipt_id = receipt_item.receipt_id
and Date(receipt.receipt_date) between '2018-04-01' and '2018-05-03'
group by Date(receipt.receipt_date)
) as table2
)
WHERE table1.reading_date = table2.receipt_date;
this solve my problem

Return 1 or 0 in SQL depending on the multiple statements

If I find that some of the user exists with such a parameters, I want to get 1 otherwise 0. In the future I'll have to add more blocks. But it doesn't seem to work now. What am I doing wrong?
SELECT CAST(CASE WHEN EXISTS(SELECT 1
FROM Customers
WHERE Country = 'France' AND PostalCode%2 = 0)
OR (WHERE Country = 'Germany' AND PostalCode%2 = 0))
)
THEN 1
ELSE 0
END AS BIT)
You need two separate exists:
SELECT CAST(CASE WHEN EXISTS (SELECT 1
FROM Customers
WHERE Country = 'France' AND PostalCode%2 = 0
)
THEN 1
WHEN EXISTS (SELECT 1
FROM Customers
WHERE Country = 'Germany' AND PostalCode%2 = 0
)
THEN 1
ELSE 0
END AS BIT)
Actually, I broke this into two separate THEN clauses. This is almost equivalent to using OR, but because the logic is inside a CASE, THEN seems more natural. (The difference is that the optimizer could choose to re-arrange the OR conditions, but the THEN conditions are executed in lexical order.)
If your statements are actually this simple, you can combine them as:
SELECT CAST(CASE WHEN EXISTS (SELECT 1
FROM Customers
WHERE Country IN ('France', 'Germany') AND PostalCode%2 = 0
)
THEN 1
ELSE 0
END AS BIT)
It looks to me like you're just having issues with your bracketing:
SELECT CAST(
CASE WHEN EXISTS(
SELECT 1
FROM Customers
WHERE (Country = 'France' AND PostalCode%2 = 0)
OR (Country = 'Germany' AND PostalCode%2 = 0)
) THEN 1 ELSE 0 END AS BIT)
Building on Gordon's assumption that PostalCode%2 = 0 for all tested 'sets' of conditionals (you haven't said as much yet), you could likewise shorten this to:
SELECT CAST(
CASE WHEN EXISTS(
SELECT 1
FROM Customers
WHERE PostalCode%2 = 0
AND Country IN ('France', 'Germany')
) THEN 1 ELSE 0 END AS BIT)

MySQL How to make a SELECT SUM from Table and multiplication from other SEARCH?

I have this query
SELECT ps_ur AS UR, COUNT(ps_ur) AS Value
FROM patient_services
GROUP BY UR
UNION ALL
SELECT eng_ur AS UR, COUNT(eng_ur) AS Value
FROM engagements
WHERE LENGTH( eng_ur )>0
GROUP BY UR
Result:
UR Value
002035 3
002400 2
005441 4
...
Now I need to calculate from Patient table Male/Female and multiply by the Value
Like this but right
SELECT
SUM( CASE WHEN patient_gender = 'Male' THEN 1 ELSE 0 END ) Male,
SUM( CASE WHEN patient_gender = 'Female' THEN 1 ELSE 0 END ) Female
FROM patients WHERE patient_ur
How to do this?
In that case you want wrap the first as inner query. Something like below. Now you can access the Value field saying xxx.Value and multiply or do whatever processing needed. Not sure where you want to multiply and thus couldn't reflect it in suggested query. Probably that's left as homework for you.
SELECT
SUM( CASE WHEN patient_gender = 'Male' THEN 1 ELSE 0 END ) Male,
SUM( CASE WHEN patient_gender = 'Female' THEN 1 ELSE 0 END ) Female
FROM patients JOIN (
SELECT ps_ur AS UR, COUNT(ps_ur) AS `Value`
FROM patient_services
GROUP BY UR
UNION ALL
SELECT eng_ur AS UR, COUNT(eng_ur) AS `Value`
FROM engagements
WHERE LENGTH( eng_ur )>0
GROUP BY UR ) xxx ON patients.patient_ur = xxx.UR