Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Scenario:
A factory producing steel pipes every day in various sizes and gauges (swg), are logged and stored in the pipe_production table (pipe_id foreign key to pipe table). The factory also has clients to which it regularly sells pipes, upon request an invoice is created and logged in the invoices table. Subsequently, the related pipes relative to each invoice are stored in the pipe_invoices table. When a member of the sales team authorises the invoice, the authorised column switches from false to true (0 => 1 in) in the invoices table and signals that that these pipes will be sold and should be removed from the stock.
I'm looking for a query to produce a stock table to accurately assess the pipe onsite. However I'm only looking to find only the difference between pipes produced and AUTHORISED invoice pipes.
The application is being built on the Laravel framework.
Table: pipes
id | description | swg | min_weight | max_weight
1 | 2" X 2" | 16 | 10 | 11
2 | 2" X 2" | 18 | 8 | 19
3 | 1" X 2" | 18 | 4 | 6
Table: pipe_productions
id | pipe_id | quantity | production_date
1 | 1 | 1000 | 2020-10-1
2 | 2 | 2000 | 2020-10-1
3 | 3 | 5500 | 2020-10-1
Table: invoices
id | client_id | authorised | loaded | invoice_date
1 | 1 | 0 | 0 | 2020-10-09
2 | 2 | 1 | 0 | 2020-10-09
3 | 2 | 1 | 1 | 2020-10-09
Table: pipe_invoices
id | invoice_id | pipe_id | quantity
1 | 1 | 3 | 2000
2 | 1 | 1 | 1000
3 | 2 | 2 | 1000
Edit:
My Current query which only gets the difference between pipe_production and pipe_invoices. It does not account for the case where the invoice is not authorised and should not be removed.
SELECT *, coalesce(a.quantity, 0)-coalesce(b.quantity, 0) as diff
FROM
(SELECT pipe_id, sum(quantity) as quantity
FROM pipe_productions
GROUP BY pipe_id) a
LEFT JOIN
(SELECT pipe_id, sum(quantity) as quantity
FROM pipe_invoices
GROUP BY pipe_id) b
on a.pipe_id = b.pipe_id
LEFT JOIN pipes
on a.pipe_id = pipes.id
WHERE coalesce(a.quantity, 0)-coalesce(b.quantity, 0) != 0
ORDER BY swg asc, pipe_description desc
I assume that you only need to a small adaption to your query and join invoices in your b statement:
SELECT *, coalesce(a.quantity, 0)-coalesce(b.quantity, 0) as diff
FROM
(
SELECT pipe_id, sum(quantity) as quantity
FROM pipe_productions
GROUP BY pipe_id
) a
LEFT JOIN
(
SELECT pipe_id, sum(quantity) as quantity
FROM pipe_invoices pi
JOIN invoices i ON pi.invoice_id = i.id
WHERE i.authorised = 1
GROUP BY pipe_id
) b
on a.pipe_id = b.pipe_id
LEFT JOIN pipes
on a.pipe_id = pipes.id
WHERE coalesce(a.quantity, 0)-coalesce(b.quantity, 0) != 0
ORDER BY swg asc, pipe_description desc
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 months ago.
Improve this question
Query Result
date_created
sub_total
total_amount
budget_id
10000
2022-09-25
700
9300
1
2022-09-21
500
8800
1
2022-09-15
900
7900
1
2022-09-01
500
7400
1
7400
Budget Table
id
budget
1
10000
Here's my query
SELECT date_created, sub_total,
budget - LAG(sub_total) OVER (ORDER BY date_created DESC)
as total_amount
FROM sales
LEFT JOIN budget_table ON budget.id = sales.budget_id
WHERE budget_id = 1
ORDER BY date_created DESC
Union to get start and end position and subtract cumulative sum from budget to get detail (lag is inappropriate here). prepend a seq to assist ordering
DROP TABLE IF EXISTS T,T1;
CREATE TABLE T
(date_created DATE,SUB_TOTAL INT,BUDGET_ID INT);
INSERT INTO T VALUES
('2022-09-25' ,700, 1),
('2022-09-21' ,500, 1),
('2022-09-15' ,900, 1),
('2022-09-01' ,500, 1);
CREATE TABLE T1(BUDGET_ID INT,BUDGET INT);
INSERT INTO T1 VALUES (1,10000);
SELECT 2 SEQ,T.BUDGET_ID,date_created, sub_total,
BUDGET - SUM(sub_total) OVER (ORDER BY date_created DESC) TOTAL_AMOUNT
FROM T
LEFT JOIN T1 ON T1.budget_id = T.budget_id
WHERE T.budget_id = 1
UNION ALL
SELECT 1 AS SEQ, T1.BUDGET_ID,NULL,NULL,T1.BUDGET FROM T1
UNION ALL
SELECT 3 AS SEQ, T.BUDGET_ID,NULL,NULL,
BUDGET - SUM(sub_total) TOTAL_AMOUNT
FROM T
LEFT JOIN T1 ON T1.budget_id = T.budget_id
WHERE T.budget_id = 1
ORDER BY BUDGET_ID,SEQ,date_created DESC
+-----+-----------+--------------+-----------+--------------+
| SEQ | BUDGET_ID | date_created | sub_total | TOTAL_AMOUNT |
+-----+-----------+--------------+-----------+--------------+
| 1 | 1 | NULL | NULL | 10000 |
| 2 | 1 | 2022-09-25 | 700 | 9300 |
| 2 | 1 | 2022-09-21 | 500 | 8800 |
| 2 | 1 | 2022-09-15 | 900 | 7900 |
| 2 | 1 | 2022-09-01 | 500 | 7400 |
| 3 | 1 | NULL | NULL | 7400 |
+-----+-----------+--------------+-----------+--------------+
6 rows in set (0.002 sec)
This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Get records with max value for each group of grouped SQL results
(19 answers)
Closed 4 years ago.
I want to join these two tables, showing the most recent due date for every client:
Table "clients":
| id_client | name |
|-----------|------------|
| 1 | Customer 1 |
| 2 | Customer 2 |
| 3 | Customer 3 |
Table "invoices" (FK id_client):
| id_invoice | id_client | due_date | payment_frequency |
|------------|-----------|------------|-------------------|
| 1 | 1 | 2018-11-30 | monthly |
| 2 | 1 | 2018-12-30 | monthly |
| 3 | 2 | 2019-01-01 | quarterly |
| 4 | 2 | 2019-01-01 | quarterly |
Desired result:
| id_client | name | due_date | payment_frequency |
|-----------|------------|------------|-------------------|
| 1 | Customer 1 | 2018-12-30 | monthly |
| 2 | Customer 2 | 2019-01-01 | quarterly |
| 3 | Customer 3 | (null) | (null) |
Details:
It should return all clients records, even those with no invoices (null).
Some customers have more than one invoice that due on the same date (id_invoice 3 and 4 in this example), but only one record should be returned.
I was able to make it work through the following query:
SELECT
c.id_client,c.name,
(SELECT due_date FROM invoices WHERE id_client=c.id_client ORDER BY due_date DESC LIMIT 1) AS due_date,
(SELECT payment_frequency FROM invoices WHERE id_client=c.id_client ORDER BY due_date DESC LIMIT 1) AS payment_frequency
FROM
clients AS c
I think there are more elegant and better-performing ways, through joins. Can you give me your suggestion please?
This table structure, data and query at Fiddle
Ps. Despite the question is marked as a duplicate, other questions and answers do not solve this case.
Please check this out
select
c.id_client,
c.name,
max(i.due_date) due_date,
max(i.payment_frequency) payment_frequency
from clients c
left outer join invoices i
on c.id_client = i.id_client
group by
c.id_client,
c.name
Edit: Please check my edited answer
select
c.id_client,
c.name,
i.due_date due_date,
i.payment_frequency payment_frequency
from clients c
left outer join invoices i
on c.id_client = i.id_client
where due_date is null or due_date = (select max(due_date) from invoices where id_client = i.id_client)
group by c.id_client, c.name, i.due_date, i.payment_frequency
This question already has answers here:
How can I SELECT rows with MAX(Column value), PARTITION by another column in MYSQL?
(22 answers)
Closed 4 years ago.
I have 2 tables:
manifests
id | customer | paid_order | price | payment_method
paid_orders
id | paid
JOIN paid_orders ON manifests.paid_order = paid_order_id
Let's assume this scenario:
There are 2 same customer but has different payment_method.
customer | paid_order | price | payment_method | paid |
1 | 1 | 200 | 0 | 200 |
1 | NULL | 100 | 1 | NULL |
2 | NULL | 150 | 1 | NULL |
I only want to GROUP BY customer but also PICK only the payment_method of 0 only if there are two same customer.
Expected result:
customer | paid_order | price | payment_method | paid |
1 | 1 | 200 | 0 | 200 |
2 | NULL | 150 | 1 | NULL |
One approach would be to always select the record from one, or possibly more, customer records where the payment_method has the minimum value:
SELECT m1.*
FROM manifest m1
INNER JOIN
(
SELECT customer, MIN(payment_method) AS min_payment_method
FROM manifest
GROUP BY customer
) m2
ON m1.customer = m2.customer AND m1.payment_method = m2.min_payment_method;
This logic should work, because if a payment_method of zero be present, then this record would be targeted. Otherwise, the one value record would be targeted.
I'd like a little help here.
I'm building a database in MySQL where I will have a bunch of different activities. Each activity is part of a list.
So, I have the following tables on my database.
List
id
name
Activity
id
name
idList (FK to List)
I also want to know when each activity is finished (you can finish the same activity many times). To accomplish that, I have another table:
History
date
idActivity (FK to activity)
When the user finishes an activity, I add the id of this activity and the current time the activity was finished, to the History table.
I want to get the entire list with the date it was finished. When an activity has not been finished, I want it to show the date as null.
But, getting the list just once is easy. A simple Left Outer Join will do the trick. My issue here is that I want to get the ENTIRE list everytime a date appears on the history table.
This is what I'm looking for:
List:
id | name
1 | list1
Activity:
id | name | idList
1 | Activity1 | 1
2 | Activity2 | 1
3 | Activity3 | 1
4 | Activity4 | 1
5 | Activity5 | 1
6 | Activity6 | 1
History:
date | idActivity
17/07/14 | 1
17/07/14 | 3
17/07/14 | 4
17/07/14 | 6
16/07/14 | 2
16/07/14 | 3
16/07/14 | 5
Expected Result:
idActivity | idList | activityName | date
1 | 1 | Activity1 | 17/07/14
2 | 1 | Activity2 | NULL
3 | 1 | Activity3 | 17/07/14
4 | 1 | Activity4 | 17/07/14
5 | 1 | Activity5 | NULL
6 | 1 | Activity6 | 17/07/14
1 | 1 | Activity1 | NULL
2 | 1 | Activity2 | 16/07/14
3 | 1 | Activity3 | 16/07/14
4 | 1 | Activity4 | NULL
5 | 1 | Activity5 | 16/07/14
6 | 1 | Activity6 | NULL
The "trick" is to use a CROSS JOIN (or semi-cross join) operation with a distinct list of dates from the history table, to produce the set of rows you want to return.
Then a LEFT JOIN (outer join) to the history table to find the matching history rows.
Something like this:
SELECT a.id AS idActivity
, a.idList AS idList
, a.name AS activityName
, h.date AS `date`
FROM activity a
CROSS
JOIN ( SELECT s.date
FROM history s
GROUP BY s.date
) r
LEFT
JOIN history h
ON h.idActivity = a.id
AND h.date = r.date
ORDER
BY r.date
, a.id
That query gets the six rows from activity, and two rows (distinct values of date) from history (inline view aliased as r). The CROSS JOIN operation matches each of the six rows with each of the two rows, to produce a Cartesian product of 12 rows.
To get the rows returned in the specified order, we order by date, and then by activity.id.
I have the following data structure:
Table 1(groups):
ID | Group
=============
1 | Sample
2 | Data
Table 2(items):
ID | GroupID | Cost | Amount
==============================
1 | 1 | 1 | 12
2 | 1 | 7 | 15
3 | 1 | 3 | 8
4 | 2 | 2 | 12
And would like the following (query) results:
groups.ID | groups.Name | total
1 | Sample | 141
2 | Data | 24
total is the sum over the products of cost and amount of all items in the group i.e. for group 1: 1*12+7*15+3*8=141
Im guessing I have to something with
SELECT g.ID, g.Group, SUM(Products)
FROM groups AS g, items AS i
WHERE g.ID=i.GroupID
GROUP BY i.GroupID
But don't know what exactly.
Doing iit in clientsoftware with loops is no problem, but I am curious (and certain) that this can be done in (my)Sql
SELECT g.ID as ID, g.Group as Name, SUM(i.Cost * i.Amount) as total
FROM groups g
INNER JOIN items i ON i.GroupID = g.ID
GROUP BY g.Group, g.ID
Having a field named "Group" is quite a bad idea in SQL (reserved keyword)