combining two select statements with group by and order by - mysql

I have the following 2 select statements that work and return the info on their own, but was wondering if there was a way to join / combine them into one report with their own separate rows and columns
Select Sum (amount) as PDCGross
From Desk D Left Join
Master M
on D.code = M.desk INNER JOIN
pdc
ON m.number = pdc.number
Where teamid = 3
AND active = 1
And onhold is NULL
And deposit >='2020-10-01'
And deposit <= '2020-10-31'
Group by D.Name
Order by desk.Name Desc
Select Sum (amount) as GrossPDCC
FROM Desk D left JOIN
Master M
on D.code = M.Desk INNER JOIN
DebtorCreditCards P
ON m.number = P.Number
Where teamid = 3
AND IsActive = 1
And OnHoldDate is NULL
And DepositDate >='2020-10-01'
And DepositDate <= '2020-10-31'
Group by D.Name
Order by desk.Name Desc
The return for the 1st statement
PDCPross
2500
1500
1300
The result of the 2nd statement is
PDCCGross
1500
1300
1000
What i am looking for is
PDCPross PDCCGross
2500 1500
1500 1300
1300 1000

On MySQL v 8.0+ or MariaDB 10.2 +, you can use ROW_NUMBER() function:
Assign each query with ROW_NUMBER() then make both query as sub-query. Join the queries using the rownum result and you should be able to see your results side by side. Something like this query example:
SELECT A.PDCGross, B.GrossPDCC FROM
(SELECT ROW_NUMBER() OVER (ORDER BY D.Name DESC) AS rownum, SUM(amount) AS PDCGross
FROM Desk D LEFT JOIN
MASTER M
ON D.code = M.desk INNER JOIN
pdc
ON m.number = pdc.number
WHERE teamid = 3
AND active = 1
AND onhold IS NULL
AND deposit >='2020-10-01'
AND deposit <= '2020-10-31'
GROUP BY D.Name
ORDER BY D.Name DESC) A JOIN
(SELECT ROW_NUMBER() OVER (ORDER BY D.Name DESC) AS rownum, SUM(amount) AS GrossPDCC
FROM Desk D LEFT JOIN
MASTER M
ON D.code = M.Desk INNER JOIN
DebtorCreditCards P
ON m.number = P.Number
WHERE teamid = 3
AND IsActive = 1
AND OnHoldDate IS NULL
AND DepositDate >='2020-10-01'
AND DepositDate <= '2020-10-31'
GROUP BY D.Name
ORDER BY D.Name DESC) B ON A.rownum=B.rownum;

Related

How can I change the range of duplicates from month to day?

mysql is
SELECT date_format(dt.d, '%Y-%m') as date_list,
COUNT(distinct c.id) AS cnt
FROM date_t dt
LEFT OUTER JOIN login_logs c on dt.d = DATE(c.reg_date)
WHERE LEFT(dt.d,7) BETWEEN '2021-05-01' AND '2022-04-25'
GROUP BY date_list
ORDER BY date_list;
the result i want is,
c.id is 2022-04-01 , 2022-04-02 => count 2
but I am getting:
c.id is 2022-04 => count 1
how can I change distinct 'c.id' daily check ?

MySQL left join with sub query produces different results with different sorting

I have 2 tables: invoices and paymentTransactions. where table paymentTransactions contains entries of payment transactions of invoices - may have multiple entries.
Table: invoices:
invoiceId, customerId, amount
Table: paymentTransactions:
paymentTransactionId, invoiceId, status
The requirement is to get the invoices along with the latest payment transaction log.
I tried the below query, but it is returning different results with different sorting.
SELECT i.invoiceId,recentTrans.maxTransId, cts.status as recentStatus FROM invoices i LEFT JOIN (SELECT MAX(paymentTransactionId) AS maxTransId, invoiceId FROM paymentTransactions GROUP BY invoiceId) recentTrans ON recentTrans.invoiceId = i.invoiceId LEFT JOIN paymentTransactions cts ON cts.paymentTransactionId = recentTrans.maxTransId AND cts.invoiceId = recentTrans.invoiceId WHERE i.invoiceId IN(130623, 3062) GROUP BY i.invoiceId ORDER BY `invoiceId` desc;
Actually, there is no payment transaction for invoiceId: 130623, but the recentStatus is returning as 1. It is expected to return NULL.
Data:
invoices:
invoiceId customerId amount
3062 1 40
130623 2 60
paymentTransactions:
paymentTransactionId, invoiceId, status
305 3062 2
306 3062 1
Appreciating all replies.
Thank you
You are getting unexpected results because in the SELECT list there are non aggregated columns which are not included in the GROUP BY clause.
But you don't need the GROUP BY clause:
SELECT i.invoiceId, cts.paymentTransactionId maxTransId, cts.status as recentStatus
FROM invoices i
LEFT JOIN (
SELECT MAX(paymentTransactionId) AS maxTransId, invoiceId
FROM paymentTransactions
GROUP BY invoiceId
) recentTrans ON recentTrans.invoiceId = i.invoiceId
LEFT JOIN paymentTransactions cts
ON cts.paymentTransactionId = recentTrans.maxTransId AND cts.invoiceId = i.invoiceId
WHERE i.invoiceId IN (130623, 3062)
ORDER BY i.invoiceId ASC;
or with a correlated subquery:
SELECT i.invoiceId, pt.paymentTransactionId maxTransId, pt.status as recentStatus
FROM invoices i LEFT JOIN paymentTransactions pt
ON pt.invoiceId = i.invoiceId
AND pt.paymentTransactionId = (
SELECT MAX(paymentTransactionId)
FROM paymentTransactions
WHERE invoiceId = i.invoiceId
)
WHERE i.invoiceId IN (130623, 3062)
ORDER BY i.invoiceId ASC;
or if your version of MySql is 8.0+ use a CTE with ROW_NUMBER() window function:
WITH pt AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY invoiceId ORDER BY paymentTransactionId DESC) rn
FROM paymentTransactions
)
SELECT i.invoiceId, pt.paymentTransactionId maxTransId, pt.status as recentStatus
FROM invoices i LEFT JOIN pt
ON pt.invoiceId = i.invoiceId AND pt.rn = 1
WHERE i.invoiceId IN (130623, 3062)
ORDER BY i.invoiceId ASC;
See the demo.
> invoiceId | maxTransId | recentStatus
> --------: | ---------: | -----------:
> 3062 | 306 | 1
> 130623 | null | null

Assign a position value to row based on a SUM

I'm using the code below to get the total distance for teams that people have registered to and entered data, then assign a position to the team.
SELECT #curRow := #curRow + 1 AS position, ROUND(SUM(d.dist_activity_duration
* CASE
WHEN d.dist_is_distance = 0 THEN s.activity_steps / 2000
WHEN d.dist_is_distance = 1 THEN 1
END)
,2) AS miles, t.team_name AS team_name
FROM distance d
JOIN (SELECT #curRow := 0) r
JOIN activities a
ON a.id = d.dist_activity_id
JOIN steps s
ON s.id = a.steps_id
JOIN members AS m
ON d.member_id = m.id
JOIN teams AS t
ON t.id = m.member_team_id
GROUP BY team_name
ORDER BY miles DESC
The code above outputs the following results
position miles team_name
2 134.05 team 1
1 78.00 team 2
I would like position 1 to be assigned to the team with the highest miles, position 2 the 2nd highest team...and so on.
In MySQL 8+, you would just use row_number():
SELECT ROW_NUMBER() OVER (ORDER BY miles DESC) AS position, t.*
FROM (SELECT ROUND(SUM(d.dist_activity_duration *
CASE WHEN d.dist_is_distance = 0 THEN s.activity_steps / 2000
WHEN d.dist_is_distance = 1 THEN 1
END), 2) AS miles, t.team_name AS team_name
FROM distance d JOIN
activities a
ON a.id = d.dist_activity_id JOIN
steps s
ON s.id = a.steps_id JOIN
members m
ON d.member_id = m.id JOIN
teams t
ON t.id = m.member_team_id
GROUP BY team_name
) t
ORDER BY miles DESC;
Earlier versions of MySQL support variables but they do not play well with GROUP BY and ORDER BY. The solution is a subquery (as above):
SELECT (#rn := #rn + 1) AS position,
FROM (SELECT ROUND(SUM(d.dist_activity_duration *
CASE WHEN d.dist_is_distance = 0 THEN s.activity_steps / 2000
WHEN d.dist_is_distance = 1 THEN 1
END), 2) AS miles, t.team_name AS team_name
FROM distance d JOIN
activities a
ON a.id = d.dist_activity_id JOIN
steps s
ON s.id = a.steps_id JOIN
members m
ON d.member_id = m.id JOIN
teams t
ON t.id = m.member_team_id
GROUP BY team_name
ORDER BY miles DESC
) t CROSS JOIN
(SELECT #rn := 0) params;
This works for me.
SELECT (#rn := #rn + 1) AS position, team_name, miles
FROM (SELECT ROUND(SUM(d.dist_activity_duration
* CASE
WHEN d.dist_is_distance = 0 THEN s.activity_steps / 2000
WHEN d.dist_is_distance = 1 THEN 1
END)
,2) AS miles, t.team_name AS team_name
FROM distance d
JOIN activities a
ON a.id = d.dist_activity_id
JOIN steps s
ON s.id = a.steps_id
JOIN members AS m
ON d.member_id = m.id
JOIN teams AS t
ON t.id = m.member_team_id
GROUP BY team_name
ORDER BY miles DESC
) t CROSS JOIN
(SELECT #rn := 0) params;

Group and count rows and then use them in condition

I have an query like:
SELECT * FROM account AS a
LEFT JOIN (SELECT SUM(bill.amount) total, bill.accountId FROM bill GROUP BY bill.accountId) b ON a.id = b.accountId
WHERE a.partner_id = 1 OR a.partner_id = 2
How can I check, how many groups in "bill" has the same a.partner_id?
For example: 3 groups has partner_id = 1, 2 groups has partner_id = 2.
And later include to left join only groups, if more than 2 groups have the same partner_id.
If I understand correctly, you just want an aggregation on top of your query:
SELECT a.partner_id, count(*) as cnt, sum(total) as total
FROM account a LEFT JOIN
(SELECT SUM(b.amount) as total, b.accountId
FROM bill b
GROUP BY b.accountId
) b
ON a.id = b.accountId
GROUP BY a.partner_id;
You should be able to use the "HAVING" clause. Below is an example from the following link:
https://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
SELECT name, COUNT(name) AS c FROM orders
GROUP BY name
HAVING c = 1;

Getting both max and min sum values on mysql

Good day everyone I would like a query that can give me both maximum and minimum sum values. Specifically i have the following tables:
PRODUCT
_____________________________
productID | categoryID| name|
__________|___________|_____|
1 1 "name1"
2 1 "name2"
3 1 "name3"
4 2 "name4"
5 2 "name5"
6 1 "name6"
7 2 "name7"
8 2 "name8"
AND:
PURCHASES
_____________________________
purchaseID | productID| quantity|
___________|___________|_________|
1 1 12
2 2 13
3 4 55
4 4 66
5 5 99
6 6 99
7 5 88
8 7 12
so basically i have to show the product that was bought the most and the product that was bought the least.. T have tried this:
SELECT pr.name, max(sum(p2.quantity))
FROM purchase as p2, product as pr
WHERE p2.IDproduct=pr.IDproduct
Group by p2.IDproduct desc
but I get Error Code 1111: Invalid use of group function.
For max Product
select t.name,max(t.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t
group by t.name order by MaxProduct desc limit 1
FOR COMBINE RESULT
(select t.name,max(t.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t
group by t.name order by MaxProduct desc limit 1)
UNION ALL
(select t1.name,min(t1.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t1
group by t1.name order by MaxProduct asc limit 1)
SQL FIDDLE
Hacky, but it works
(
SELECT
SUM(pur.quantity) quant,
prod.name name
FROM Purchases pur
INNER JOIN Products prod
ON prod.productID = pur.productID
GROUP BY pur.productID
ORDER BY quant DESC
LIMIT 1
)
UNION
(
SELECT
SUM(pur.quantity) quant,
prod.name name
FROM Purchases pur
INNER JOIN Products prod
ON prod.productID = pur.productID
GROUP BY pur.productID
ORDER BY quant ASC
LIMIT 1
)
SQLFiddle
As I received a Cannot perform an aggregate function on an expression containing an aggregate or a subquery as an error error.
For others encountering the problem of using the SUM function inside of a MAX function, but not having the same issue as OP, based on Luv's answer, I was able to convert the following Scalar-valued function:
SELECT #MinMaxValue = MAX(SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal))
FROM ArtikelM
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
to
SELECT #MinMaxValue = MAX(selectedsum.sumx)
FROM (
SELECT SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal) AS sumx
FROM ArtikelM
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
) AS selectedsum
or if ArtikelM.Aantal could be zero
SELECT sumx =
CASE
WHEN SUM(ArtikelM.Aantal) > 0
THEN SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal)
ELSE MIN(Leverancier.FactPrijs)
END
FROM ArtikelM
INNER JOIN Leverancier
ON ArtikelM.LevId = Leverancier.LevId
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
) AS selectedsum
I think this might help out others too
Select max(product_id), min(product_id)
from Purchases Where Product_id In
(select product_id, Sum(quantity) from Purchases Group by product_id)