MySQL row into number of columns sum and payment option [duplicate] - mysql

This question already has answers here:
MySQL row into number of columns and sum
(3 answers)
Closed 5 years ago.
I have a table with records such as:
ID | Car_num | Service | Price | Payment
---+---------+---------+-------+-------+-
1 | 001 | shower | 10 | card
2 | 002 | TV | 5 | cash
3 | 001 | TV | 5 | cash
How to write an SQL query to get the following output?
ID |Car_num | shower | TV
---+--------+------------+---
1 | 001 | 10 (card) | 5 (cash)
2 | 002 | | 5 (cash)

Use conditional aggregation:
SELECT MIN(t.id) as id,
t.car_num,
MAX(CASE WHEN t.service = 'shower' THEN t.price END) as shower,
MAX(CASE WHEN t.service = 'TV' THEN t.price END) as TV
FROM YourTable t
GROUP BY t.car_num
If you want the columns to actually appear like 10 (card) and not 10 (which is not recommended at all), then change it to this:
MAX(CASE WHEN t.service = 'shower' THEN concat(t.price,'(',t.payment,')') END) as shower,
MAX(CASE WHEN t.service = 'TV' THEN concat(t.price,'(',t.payment,')') END) as TV

Related

SQL difference between 2 table columns [closed]

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

MySQL - Join two tables by most recent date [duplicate]

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

SQL Increment Column

I am trying to show one semesters aggregates in one column, the next semester's aggregates in the second column, and the third semesters aggregates in the third column. Also the real tables, I don't know how many status codes there are...
I have a semester table:
Id Semester
+----+----------+
| 1 Current |
| 2 Next |
| 3 2 Ahead |
+----+----------+
I have a simple project table:
Id Title Status termId
+----+--------+---------+--------+
| 1 A OK 1 |
| 2 B Bad 1 |
| 3 C OK 1 |
| 4 D Bad 2 |
| 5 E OK 2 |
| 6 F Bad 3 |
| 7 G OK 2 |
+----+--------+---------+--------+
This is the desired Output:
Status CurrentCount NextCount 2AheadCount
+---------+--------------+-----------+-------------+
| OK 2 1 0 |
| Bad 1 1 1 |
+---------+--------------+-----------+-------------+
What would you recommend I do to be able to achieve this?
You can use conditional aggregation with group by:
select status,
sum(case when termId = 1 then 1 else 0 end) CurrentCount,
sum(case when termId = 2 then 1 else 0 end) NextCount,
sum(case when termId = 3 then 1 else 0 end) 2AheadCount
from project
group by status

how can I print multiple rows data in one column?

I having two table with mysql as below?
TimeSchedule
subID | date | venue | timeslot
1 | 8-12 | ABC | 10 - 12
2 | 8-12 | ABC | 2 - 4
subject
subID | name
1 | Games
2 | Music
I want to display these two table data as following?
Date | 10 - 12 | 2 - 4 |Venue
8-12 | Game | Music | ABC
Try this:
SELECT t.date,
MAX(CASE WHEN t.timeslot = '10 - 12' THEN s.name ELSE '' END) AS `10 - 12`,
MAX(CASE WHEN t.timeslot = '2 - 4' THEN s.name ELSE '' END) AS `2 - 4`,
t.venue
FROM TimeSchedule t
INNER JOIN `subject` s ON t.subID = s.subID
GROUP BY t.date;

Denormalize the data

I have three normalized Tables as follows
person_info person_phone phone_types
------------ ------------------------------- --------------
| id | Name | | p_id | typeid | value | | id | type |
|----|-------| |---------|-----------|--------| |----|---------|
| 1 | Sam | | 1 | 1 | 4455544| | 1 | landline|
| 2 | Bill | | 1 | 1 | 889898 | | 2 | mobile |
| 3 | Ted | | 1 | 2 | 8898999| | 3 | fax |
------------ ------------------------------ --------------
Every person can have more than one mobile or Landline or Fax. In the above example "SAM" has two landline numbers and 1 mobile number.
I am trying to retrieve the data for SAM as follows
SELECT
pi.id,
pi.name,
MAX(CASE WHEN pt.type = 'landline' THEN pp.value ELSE NULL END) AS landline,
MAX(CASE WHEN pt.type = 'mobile' THEN pp.value ELSE NULL END) AS mobile,
MAX(CASE WHEN pt.type = 'fax' THEN pp.value ELSE NULL END) AS fax,
FROM
person_phone as pp
INNER JOIN phone_types AS pt on pp.type_id=pt.id
INNER JOIN person_info AS pi on pi.id =pp.p_id
GROUP BY pi.id;
This gives me just the last added phone number for each time.
id name landline mobile fax
1 Sam 889898 8898999 NULL
but I want all the contact numbers which they enter(It can be 'n' number of landline/mobile numbers for each person) displayed as landline1, landline2, landline3 and so on.
If my method is wrong, please suggest some other proper method.
EDIT
I am changing the condition from 'n' to a fixed number. No person can have more than 5 Landline, 5 mobile and 2 fax numbers. So there is a Maximum number limit per person now.
The solution that comes to mind is to use group concat to get all the numbers, delimited with something, and then let the application handle the presentation.