I have a following query:
SELECT COUNT (*) AS Total, Program, Status
FROM APP_PGM_CHOICE
WHERE Program IN ( 'EX', 'IM')
AND APP_PGM_REQ_DT >= '20150101'
AND APP_PGM_REQ_DT <= '20150131'
AND Status IN ( 'PE','DN','AP')
GROUP BY Program, Status
ORDER BY Program, Status
And the output is:
Total Program Status
12246 "EX" "AP"
13963 "EX" "DN"
21317 "EX" "PE"
540 "IM" "AP"
2110 "IM" "DN"
7184 "IM" "PE"
And I want the output like:
Total1 Program1 Total2 Program2 Status
12246 EX 540 IM AP
13963 EX 2110 IM DN
21317 EX 7184 IM PE
Can I do ii? If yes whats the way?
Yes you could do it this way:
Select T1.Total Total1, T1.Program Program1, T2.Total Total2, T2.Program Program2, T1.Status
From
(SELECT COUNT (*) AS Total, Program, Status
FROM APP_PGM_CHOICE
WHERE Program = 'EX'
AND APP_PGM_REQ_DT >= '20150101'
AND APP_PGM_REQ_DT <= '20150131'
AND Status IN ( 'PE','DN','AP')
GROUP BY Program, Status
ORDER BY Program, Status) T1
INNER JOIN
(SELECT COUNT (*) AS Total, Program, Status
FROM APP_PGM_CHOICE
WHERE Program = 'IM'
AND APP_PGM_REQ_DT >= '20150101'
AND APP_PGM_REQ_DT <= '20150131'
AND Status IN ( 'PE','DN','AP')
GROUP BY Program, Status
ORDER BY Program, Status) T2 on T1.Status = T2.Status
You can do this with a UNION query and some simple selects
SELECT GROUP_CONCAT(total1) as total1, GROUP_CONCAT(proram1) as program1, GROUP_CONCAT(total2) as total2, GROUP_CONCAT(program2) as program2
FROM
(SELECT total AS total1, program AS program1, null AS total2, null AS program2
WHERE program = 'EX'
UNION
SELECT null AS total1, null AS program1, total AS total2, program AS program2
WHERE program = 'IM') t
This is the easy way to pivot rows into columns
In sql Temp Table is Very Usefull and Easy Funda..
Easy Way to Get Output.
select Total,Prog,Status
Into #TempAA
from CGT
Where Prog='EX'
Group by Status,Total,Prog
select Total,Prog,Status
Into #TempBB
from CGT
Where Prog='IM'
Group by Status,Total,Prog
select A.Total as [Total1],A.Prog as [Program1],B.Total as [Total2],B.Prog as [Program2],A.Status
from #TempAA A
Inner join #TempBB B On b.Status =A.status
Related
So currently I have 2 tables called listings and logs table. The listings table holds a products reference number and it's current status. So suppose if it's status was Publish currently and it's sold, the status updates to Sold. Here the refno. in this table is unique since the status can change for 1 product.
Now I have another table called Logs table, this table records all the status changes that have happened for a particular product(referenced by refno) in a particular timeframe. Suppose the Product with refno. 5 was Publish on 1st October and Sold on 2nd October, The logs table will display as:
Refno
status_from
status_to
logtime
5
Stock
Publish
2021-10-01
5
Publish
Sold
2021-10-02
This is how my tables currently look like:
Listings table:('D'=>'Draft','N'=>'Action','Y'=>'Publish')
Logs Table which I'm getting using the following statement:
SELECT refno, logtime, status_from, status_to FROM (
SELECT refno, logtime, status_from, status_to, ROW_NUMBER() OVER(PARTITION BY refno ORDER BY logtime DESC)
AS RN FROM crm_logs WHERE logtime < '2021-10-12 00:00:00' ) r
WHERE r.RN = 1 UNION SELECT refno, logtime, status_from, status_to
FROM crm_logs WHERE logtime <= '2021-10-12 00:00:00' AND logtime >= '2015-10-02 00:00:00'
ORDER BY `refno` ASC
The logs table makes a new record every status change made and passes the current timestamp as the logtime, and the listings table changes/updates the status and updates its update_date. Now to get the total listings as of today I'm using the following statement:
SELECT SUM(status_to = 'D') AS draft, SUM(status_to = 'N') AS action, SUM(status_to = 'Y') AS publish FROM `crm_listings`
And this returns all the count data for status as of the current day.
Now this is where it gets confusing for me. So suppose today the count under action is 10 and tomorrow it'll be 15, and I want to retrieve the total that was present yesterday(10). So for this what I would've to do is take todays total(15) and subtract all the places where a product was changed to draft in between yesterday and today(Total count today in listing table - count(*) where status_to='Action' from logs table). Or vice versa, if yesterday it was 10 under action and today it is 5, it should add the values from the status_from column in logs table
Note: Refno isn't unique in my logs table since a product with the same refno can be marked as publish 1 day and unpublish another, but it is unique in my listings table.
Link to dbfiddle: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=01cb3ccfda09f6ddbbbaf02ec92ca894
I am sure it can be simplifed or better. But its my query and logic :
I found status_changes per refno's and calculated total changes from the desired day to present :
select status_logs, sum(cnt_status) to_add from (
SELECT
status_to as status_logs, -1*count(*) cnt_status
FROM logs lm
where
id = (select max(id) from logs l where l.refno = lm.refno) and
logtime >= '2021-10-01 00:00:00'
group by status_to
union all
SELECT
status_from, count(*) cnt_status_from
FROM logs lm
where
id = (select max(id) from logs l where l.refno = lm.refno) and
logtime >= '2021-10-01 00:00:00'
group by status_from ) total_changes
group by status_logs
I matched the keys between listings table and logs table by converting listings table keys :
select
case status
when 'D' THEN 'Draft'
when 'A' THEN 'Action'
when 'Y' THEN 'Publish'
when 'S' THEN 'Sold'
when 'N' THEN 'Let'
END status_l ,COUNT(*) c
from listings
group by status
I joined them and add the calculations to total sum of current data.
I had to use full outer join , so i have one left and one right join with the same subqueries.
Lastly I used distinct , since it will generate same result for each joined query and used ifnull to bring the other tables status to the other column .
select distinct IFNULL(status_l, status_logs) status, counts_at_2021_10_01
from (select l.*,
logs.*,
l.c + ifnull(logs.to_add, 0) counts_at_2021_10_01
from (select case status
when 'D' THEN
'Draft'
when 'A' THEN
'Action'
when 'Y' THEN
'Publish'
when 'S' THEN
'Sold'
when 'N' THEN
'Let'
END status_l,
COUNT(*) c
from listings
group by status) l
left join (
select status_logs, sum(cnt_status) to_add
from (SELECT status_to as status_logs,
-1 * count(*) cnt_status
FROM logs lm
where id = (select max(id)
from logs l
where l.refno = lm.refno)
and logtime >= '2021-10-01 00:00:00'
group by status_to
union all
SELECT status_from, count(*) cnt_status_from
FROM logs lm
where id = (select max(id)
from logs l
where l.refno = lm.refno)
and logtime >= '2021-10-01 00:00:00'
group by status_from) total_changes
group by status_logs) logs
on logs.status_logs = l.status_l
union all
select l.*,
logs.*,
l.c + ifnull(logs.to_add, 0) counts_at_2021_05_01
from (select case status
when 'D' THEN
'Draft'
when 'A' THEN
'Action'
when 'Y' THEN
'Publish'
when 'S' THEN
'Sold'
when 'N' THEN
'Let'
END status_l,
COUNT(*) c
from listings
group by status) l
right join (
select status_logs, sum(cnt_status) to_add
from (SELECT status_to as status_logs,
-1 * count(*) cnt_status
FROM logs lm
where id = (select max(id)
from logs l
where l.refno = lm.refno)
and logtime >= '2021-10-01 00:00:00'
group by status_to
union all
SELECT status_from, count(*) cnt_status_from
FROM logs lm
where id = (select max(id)
from logs l
where l.refno = lm.refno)
and logtime >= '2021-10-01 00:00:00'
group by status_from) total_changes
group by status_logs) logs
on logs.status_logs = l.status_l) l
I have following query:
SELECT x.id , x.amount , x.amount as paid_amount , SUM(y.bal) as total, x.reciept_no
FROM (SELECT *, paid bal
FROM challan_1 ) x
JOIN (SELECT *, amount bal
FROM challan_1 ) y
ON y.id <= x.id
GROUP BY x.id
HAVING total <= '500'
it's working quite fine. And output like
And then I made a new query that is as below
SELECT *, (CASE WHEN 500-sum(amount) >= 0
THEN '0'
ELSE 500-SUM(paid) END) as pending_amt
FROM challan_1
Output is
This query returns me a Pending Amount so I need to combine both queries so how can I combine both queries.
I need this pending amount in first query.
This is My SQL Fiddle
And I need Like This. Where User Have 500 Currency And Have 3 Payment So for that situation Output Should be like this.
Where 100 Is in pending amount and 200 from user value is debited.
I don't completely understand, but here is my take on this. 500 available. There are records where payments are made. Strange enough even beyond 500, so I assume these are would-be expenses/payments if there were more money available. I stop where payments exceed the 500.
SELECT
challan.*,
SUM(addup.amount) as total_amount,
sum(addup.paid) as total_paid,
sum(addup.amount) - sum(addup.paid) as total_pending,
sum(addup.amount) <= sum(addup.paid) as status
FROM challan_1 challan
JOIN challan_1 addup ON addup.id <= challan.id
GROUP BY challan.id
HAVING sum(addup.paid) <= 500
ORDER BY challan.id;
If you want to show further records, i.e. get rid of the HAVING clause, you'll need another formula for the pending amount, for the highest paid amount possible is 500:
SELECT
challan.*,
SUM(addup.amount) as total_amount,
sum(addup.paid) as total_paid,
sum(addup.amount) - least(500, sum(addup.paid)) as total_pending,
sum(addup.amount) <= least(500, sum(addup.paid)) as status
FROM challan_1 challan
JOIN challan_1 addup ON addup.id <= challan.id
GROUP BY challan.id
ORDER BY challan.id;
Add the subquery as another join.
SELECT x.id , x.amount , x.amount as paid_amount , SUM(y.bal) as total, x.reciept_no, p.pending_amt
FROM (SELECT *, paid bal
FROM challan_1 ) x
JOIN (SELECT *, amount bal
FROM challan_1 ) y
ON y.id <= x.id
CROSS JOIN (SELECT CASE WHEN SUM(amount) <= 500
THEN '0'
ELSE 500 - SUM(paid)
END AS pending_amt
FROM challan_1) AS p
GROUP BY x.id
HAVING total <= '500'
When I want to fetch data from table it_Service_ticket. The error is
Unknown column 'it_service_ticket.xetr' in 'having clause'
how to use group by and having condition? Please help me
SELECT Assignedto,COUNT(Assignedto) as TC
,CONCAT(count(case when STATUS = 'CLOSE' then 1 else null end) * 100 / count(1), '%') as SC
,CONCAT(count(case when STATUS = 'PENDING' then 1 else null end) * 100 / count(1), '%') as PC
,SUM(TIMESTAMPDIFF(MINUTE,Request_Date, Xetr))/60 as WH ,(540-sum(TIMESTAMPDIFF(MINUTE,Request_Date, Xetr)))/60 as VH,
COUNT(Feedback_Rate)/COUNT(Assignedto)*100 as Feed_Percent,
SUM(Feedback_Rate)/(count(Feedback_Rate)*5)*5 as AVG_Feedback
FROM `it_service_ticket`
INNER JOIN `it_problem`
ON `it_service_ticket`.`it_problem_id`=`it_problem`.`it_problem_id`
INNER JOIN `city_master`
ON `it_service_ticket`.cityid=`city_master`.city_id
GROUP BY Assignedto
HAVING `it_service_ticket`.`xetr` BETWEEN '2017-01-01 12:00:00 AM' AND '2017-03-31 12:00:00 PM'
;
I think you just want where, not having:
SELECT Assignedto, COUNT(Assignedto) as TC,
CONCAT(AVG(STATUS = 'CLOSE') * 100, '%') as SC,
CONCAT(AVG(STATUS = 'PENDING') * 100, '%') as PC,
SUM(TIMESTAMPDIFF(MINUTE, Request_Date, Xetr))/60 as WH ,
(540-SUM(TIMESTAMPDIFF(MINUTE, Request_Date, Xetr)))/60 as VH,
COUNT(Feedback_Rate)/COUNT(Assignedto)*100 as Feed_Percent,
SUM(Feedback_Rate)/(count(Feedback_Rate)*5)*5 as AVG_Feedback
FROM it_service_ticket st INNER JOIN
it_problem` p
ON st.it_problem_id = p.it_problem_id INNER JOIN
`city_master` cm
ON st.cityid = cm.city_id
WHERE st.xetr BETWEEN '2017-01-01 00:00:00' AND '2017-03-31 12:00:00'
GROUP BY Assignedto;
In general, only use HAVING when you are filtering on aggregation functions.
Notes:
I simplified the logic for calculating ratios. You might want to use format() to get a particular number of decimal places.
Don't use backticks if they are not necessary. They just make the query harder to write and to read.
Similarly, table aliases make the query easier to write and to read.
Use 24-hour time formats -- much less prone to mistakes.
I question whether the calculation for Feed_Percent is correct. COUNT() counts the number of non-NULL values, so they ratio is likely to be 1.
You have to add Xetr in Select field. Without using this you cannot use having condition with Xetr.
Try this
SELECT Assignedto,COUNT(Assignedto) as TC
,CONCAT(count(case when STATUS = 'CLOSE' then 1 else null end) * 100 / count(1), '%') as SC
,CONCAT(count(case when STATUS = 'PENDING' then 1 else null end) * 100 / count(1), '%') as PC
,SUM(TIMESTAMPDIFF(MINUTE,Request_Date, Xetr))/60 as WH ,(540-sum(TIMESTAMPDIFF(MINUTE,Request_Date, Xetr)))/60 as VH,
COUNT(Feedback_Rate)/COUNT(Assignedto)*100 as Feed_Percent,
SUM(Feedback_Rate)/(count(Feedback_Rate)*5)*5 as AVG_Feedback,Xetr
FROM `it_service_ticket`
INNER JOIN `it_problem`
ON `it_service_ticket`.`it_problem_id`=`it_problem`.`it_problem_id`
INNER JOIN `city_master`
ON `it_service_ticket`.cityid=`city_master`.city_id
GROUP BY Assignedto
HAVING `it_service_ticket`.`Xetr` BETWEEN '2017-01-01 12:00:00 AM' AND '2017-03-31 12:00:00 PM';
But in My View you have to use Xetr in where clause for performance as i mentioned below :
SELECT Assignedto,COUNT(Assignedto) as TC
,CONCAT(count(case when STATUS = 'CLOSE' then 1 else null end) * 100 / count(1), '%') as SC
,CONCAT(count(case when STATUS = 'PENDING' then 1 else null end) * 100 / count(1), '%') as PC
,SUM(TIMESTAMPDIFF(MINUTE,Request_Date, Xetr))/60 as WH ,(540-sum(TIMESTAMPDIFF(MINUTE,Request_Date, Xetr)))/60 as VH,
COUNT(Feedback_Rate)/COUNT(Assignedto)*100 as Feed_Percent,
SUM(Feedback_Rate)/(count(Feedback_Rate)*5)*5 as AVG_Feedback,Xetr
FROM `it_service_ticket`
INNER JOIN `it_problem`
ON `it_service_ticket`.`it_problem_id`=`it_problem`.`it_problem_id`
INNER JOIN `city_master`
ON `it_service_ticket`.cityid=`city_master`.city_id
where `it_service_ticket`.`Xetr` BETWEEN '2017-01-01 12:00:00 AM' AND '2017-03-31 12:00:00 PM'
GROUP BY Assignedto;
I have a query:
SELECT
COUNT(*)
FROM
(SELECT
vendors_id,
merchants_id,
SUM(amount) AS amount,
SUM(commission_amount) AS commission_amount
FROM
(SELECT
vendors_id,
merchants_id,
amount,
commission_amount
FROM
(SELECT
vendors.id AS vendors_id,
merchants_id,
SUM(transactions_cash.amount) AS amount,
SUM(
transactions_cash.commission_amount
) AS commission_amount
FROM
ibaserver.transactions_cash,
ibaserver.vendors,
ibaserver.merchants
WHERE transactions_cash.vendors_id = vendors.id
AND TIME > 1466680920208
AND TIME <= 1466681880067
AND merchants_id = merchants.id
GROUP BY transactions_cash.merchants_id
ORDER BY transactions_cash.merchants_id) a
UNION
ALL
SELECT
vendors_id,
merchants_id,
amount,
commission_amount
FROM
(SELECT
vendors.id AS vendors_id,
merchants_id,
SUM(
transactions_cash_archive.amount
) AS amount,
SUM(
transactions_cash_archive.commission_amount
) AS commission_amount
FROM
ibaserver.transactions_cash_archive,
ibaserver.vendors,
ibaserver.merchants
WHERE transactions_cash_archive.vendors_id = vendors.id
AND TIME > 1466680920208
AND TIME <= 1466681880067
AND merchants_id = merchants.id
GROUP BY transactions_cash_archive.merchants_id
ORDER BY transactions_cash_archive.merchants_id) b) s) q
And when the inner query
SELECT
vendors_id,
name,
amount
FROM ....
returns the data, the result is returned successfully. If the inner query returns only NULL:
the entire query returns an error:
Error Code: 1048
Column 'vendors_id' cannot be null
How to return 0 in the case when the inner query returns all of a NULL?
The function you want is called COALESCE. COALESCE takes a list of arguments and returns the first non-NULL value from that list. For example the query
SELECT COALESCE(vendors_id, 0), COALESCE(name, ''), COALESCE(amount, 0)...
FROM vendors...
will return either the non-NULL column value or the specified substitution value for each column.
You can use the function:
ISNULL(colName,'new value') AS
For example:
Select A.col1,ISNULL(B.col2,'0') as col2 from Table1 A INNER JOIN Table2 B ON A.cod1=B.cod1
I have two SELECT statements that give the values "TotalSales" and "VendorPay_Com". I want to be able to subtract VendorPay_Com from TotalSales within the one MySQL statement to get the value "Outstanding_Funds" but I haven't found a reliable way to do so.
These are my two statements:
Query 1:
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold';
Query 2:
SELECT SUM(AC.Amount) AS VendorPay_Comm
FROM (
SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS `Amount` FROM COMMISSION AS C WHERE C.`status` = 'Paid') AS AC
Any help on this matter would be greatly appreciated :)
You can do it as follows :
select (select ...) - (select ...)
In your example, simply :
select
(
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold'
)
-
(
SELECT SUM(AC.Amount) AS VendorPay_Comm
FROM (
SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS `Amount` FROM COMMISSION AS C WHERE C.`status` = 'Paid') AS AC
) AS Outstanding_Funds
Try
SELECT TotalSales-VendorPay_Comm AS Outstanding_Funds
FROM
(SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold') t1,
(SELECT SUM(Amount) AS VendorPay_Comm
FROM (SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS Amount
FROM COMMISSION
WHERE Status = 'Paid') t0) t2
Here is sqlfiddle