How to concat rows in a MySQL query? - mysql

I`m running this query below:
SELECT a.id as id_order, b.id as id_service,
d.nome as service_name,
c.dente as tooth,
(SELECT count(c.dente)
FROM labpedidoservicodente c
WHERE b.id = c.idLabPedidoServico) AS total,
e.valorServico as cost
FROM labpedido a
INNER JOIN labpedidoservico b
ON a.id = b.idLabPedido
INNER JOIN labpedidoservicodente c
ON a.id = c.idLabPedido
INNER JOIN labservico d
ON b.idLabServico = d.id
INNER JOIN labservicovalor e
ON b.idLabServico = e.idLabServico
WHERE a.id = '914'
My result comes this way:
order_id service_id service_name tooth total cost
914 640 SERVICE NAME 1 11 3 80.00
914 640 SERVICE NAME 1 21 3 80.00
914 640 SERVICE NAME 1 38 3 80.00
914 641 SERVICE NAME 2 11 3 84.80
914 641 SERVICE NAME 2 21 3 84.80
914 641 SERVICE NAME 2 38 3 84.80
My desired output should be like this:
order_id service_id service_name tooth total cost
914 640 SERVICE NAME 1 11-21 2 80.00
914 641 SERVICE NAME 2 38 1 84.60
The problem is that I need to concat these rows in the column "tooth" inside their respective "service_id", have tried everything but no sucess, also the total

Replace c.dente with GROUP_CONCAT(c.dente SEPARATOR ' - ') and add GROUP BY service_id below.

Related

How to get total appointment durations from this table using sql

I have 3 mysql tables:
appointments
id slot_id patient_name doctor_id deleted_at
1 11 Tasin 23 2019-10-10
2 12 Nawaz 22 null
3 13 Rakib 23 null
4 14 Hossen 23 null
5 15 Aritra 24 null
6 16 Anik 22 null
7 17 Manik 22 null
doctors
id status doctor_name
22 1 Khaled
23 1 Hasan
24 0 Rumi
slots
id date duration time
11 2019-10-10 2900 01:01
12 2019-10-11 1200 02:01
13 2019-10-18 1100 03:01
14 2019-09-08 200 11:01
15 2019-08-01 500 01:31
16 2019-10-07 300 02:31
17 2019-10-02 1200 03:31
Now, I want to show a list of doctors with their total appointment durations in decreasing order using SQL query.
Unfortunately, I don't have any idea about this SQL query. Can you assist me?
SELECT DOCTOR_NAME, SUM(DURATION) FROM APPOINTMENTS A
JOIN DOCTORS D ON D.ID = A.DOCTOR_ID
JOIN SLOTS S ON S.ID = A.SLOT_ID
GROUP BY D.ID, DOCTOR_NAME
ORDER BY SUM(DURATION) DESC;
select d.doctor_id, d.doctor_name, sum(apt.duration) as total_duration from
doctors as d
join appointments as apt on apt.doctor_id = d.doctor_id
join slots as s on s.id = apt.slot_id
group by d.doctor_id, d.doctor_name
The above query should work fine.
There might be some typo as I didn't write it in the SQL management studio.

How to join to single row in one to many relationship in SQL?

I want to join one to many table with single row on many table by limit 1 and order by create date
tbl_cart :
id fullname
1 myname1
2 myname2
3 myname3
tbl_cart_status:
id cart_id status created_at
1 1 33 2018-09-20
2 1 34 2018-09-23
3 2 34 2018-09-21
4 1 100 2018-09-25
5 2 35 2018-09-29
How can i get output with sql like this:
I want to get lastest status of my cart by ordered with created_at column
myname cart_id status created_at
myname1 1 100 2018-09-25
myname2 2 35 2018-09-29
Think filtering for this type of query:
select c.name, cs.*
from tbl_cart c join
tbl_cart_status cs
on c.id = cs.cart_id
where cs.created_at = (select max(cs2.created_at)
from tbl_cart_status cs2
where cs2.cart_id = cs.cart_id
);

MYSQL Stuck Generating temp table (massive query)

I have 4 tables (1 to many):
Dont say anything about that "email" relation. It is how my developer boss built it years ago.
EMPLOYEES (+-50 results)
------------------------------------------------
id name
1 EmpName 1
2 EmpName 2
CUSTOMERS (+50k results)
------------------------------------------------
id name email employee_assigned
1 John john#doe.com 12
2 Donald donald#duck.com 6
INTERESTS_CATEGORIES (+650k results)
------------------------------------------------
id customer_email category_id
1 john#doe.com 97
2 john#doe.com 13
3 donald#duck.com 56
4 donald#duck.com 126
5 donald#duck.com 45
INTERESTS_PRODUCTS (+650k results)
------------------------------------------------
id customer_email product_id
1 john#doe.com 78
2 john#doe.com 23
3 donald#duck.com 19
4 donald#duck.com 56
5 donald#duck.com 45
So I need to filter the customers by their assigned employee and their interests.
And here is the query:
SELECT
*
FROM
(
SELECT
customers.id AS 'id',
customers.name AS 'first_name',
customers.email,
employees.id AS 'employee_id'
FROM
customers,
employees
WHERE
employees.id = 2
AND
customers.employee_assigned = employees.id
) AS myCustomers
LEFT JOIN interests_categories
ON interests_categories.customer_email = myCustomers.email
LEFT JOIN interests_products
ON interests_categories.customer_email = myCustomers.email
WHERE
(
interests_categories.category_id = 20
OR
interests_categories.category_id = 21
)
GROUP BY myCustomers.email
So, the problem:
If the employee has a low number of assigned customers (like 3) query
is successfull.
If the employee has a medium-high number of assigned customers (over 100) query stucks.
I execute SHOW PROCESSLIST and it is stucked "Generating temp table".
Anyone has idea? :(
Thank you.
Check the indexes on your tables and try this:
SELECT
c.id AS 'id',
c.name AS 'first_name',
c.email,
e.id AS 'employee_id'
ic.*,
ip.*
FROM customers c
JOIN employees e
ON c.employee_assigned = e.id
LEFT JOIN interests_categories ic
ON ic.customer_email = c.email
LEFT JOIN interests_products ip
ON ic.customer_email = c.email
WHERE
(
ic.category_id IN (20,21)
AND e.id = 2
)
GROUP BY myCustomers.email
Incidentally, a less dumb design might look like as follows. If it was me, I'd start with this, and provide properly representative CREATE and INSERT statements accordingly. Also, I'm curious about where category_id comes from - because that's potentially an area for further optimization.
EMPLOYEES
------------------------------------------------
employee_id name
6 EmpName 1
12 EmpName 2
CUSTOMERS
------------------------------------------------
customer_id name email employee_assigned
1 John john#doe.com 12
2 Donald donald#duck.com 6
INTERESTS_CATEGORIES
------------------------------------------------
customer_id category_id
1 97
1 13
2 56
2 126
2 45
INTERESTS_PRODUCTS
------------------------------------------------
customer_id product_id
1 78
1 23
2 19
2 56
2 45

mysql query: how to

here's my (simplified) table structure:
table: category_main
id name
-------------
1 food
2 vegetable
table category_sub
id id_catmain name
---------------------
10 1 cake
11 1 chocolate
12 1 burger
13 2 apple
14 2 banana
table images
id id_catsub filename views
-------------------------------------
1 10 cake1.jpg 11
2 10 cake2.jpg 24
3 10 cake3.jpg 65
4 11 chocolate1.jpg 31
5 11 chocolate2.jpg 62
6 11 chocolate3.jpg 32
7 11 chocolate4.jpg 58
8 12 burger1.jpg 23
9 12 burger2.jpg 43
10 12 burger3.jpg 76
11 13 apple1.jpg 29
11 13 apple2.jpg 67
11 14 banana1.jpg 78
desired output:
id name total_views
----------------------------
1 food 425
2 vegetable 174
as you can see i want to get the total views for each main category.
currently i'm running a loop for each subcategory but there must be an easier and faster way :/
thanks
Double LEFT JOIN + aggregation will do the job.
SELECT cm.id, cm.name, sum(images.views) as views
FROM category_main as cm
LEFT JOIN category_sub as cs ON cs.id_catmain = cm.id
LEFT JOIN images ON images.id_carsub = cs.id
GROUP BY cm.id
ORDER BY views DESC;
LEFT JOIN (instead of JOIN) will make you sure that you have all categories listed even if there's no subcategory or image in it. If you don't want empty categories to be listed, then use JOIN.
SELECT c.id AS id, c.name AS name, sum(i.views) AS total_views
FROM category_main c, category_sub s, images i
WHERE c.id=s.id_catmain and s.id=i.id_catsub
GROUP BY c.id,c.name;
simply join the three tables, and then you can sum the views grouped by the id's:
select cm.id, cm.name, sum(i.views) as total_views from
category_main as cm inner join category_sub as cs on cm.id = cs.id_catmain
inner join cs.id = i.id_catsub group by cm.id

How to combine many to many join?

Tables:
cust table:
cust_id, name, etc
bill table:
bill_id, cust_id, amt, due_date, status (open/closed)
payment table:
payment_id, bill_id, amt etc
Customer can settle a single bill by paying multiple installments. So, one bill_id may relate to payment_ids.
I am unable to generate this recordset:
cust_id | due amt
'due amt' is the sum of all bill.amts - sum of all payment.amts and having status open.
Bill table
bill_id cust_id amt status
1 18 200 open
2 18 200 open
3 17 200 open
4 17 200 open
5 17 200 open
6 17 200 closed
Payment table
payment_id bill_id cust_id amt
1 1 18 50
2 2 18 40
3 3 17 10
Expected output
cust_id due_amt hint/how
17 590 (600-10) .. 600 -> because one is closed
18 310 (400-(50+40))
select c.cust_id, sum(b.amt) - sum(p.amt) as due_amt
from cust c
left join bill b on b.cust_id = c.cust_id and b.status = 'open'
left join payment p on p.bill_id = b.bill_id
group by c.cust_id
SQLFiddle demo