Correct SQL statement needed in my scenario - mysql

I'm having a problem in having my desired result in my database. I want to extract Total Row Count from other table where in it's condition will be belong to the other table. To make it clear, Here is the sample illustration.
>tblBus
>
>Bus ID ~ Day~ Type
>
>1000 | Monday | Public
>2000|Monday | Private
>3000|Tuesday| Public
>4000|Monday | Public
>tblReservation
>
>Bus ID | Date
>1000 | 2013/3/4
>2000 | 2013/3/4
>3000 | 2013/3/6
Let say that the reservation day would be on Monday and that is 2013/3/4.. I want to display all PUBLIC buses that is available on Monday with a new row that has the total number of reservation made on that bus.
e.g.
GeneratedTable (WHERE Date ='2013/3/4', Type='Public', Day='Monday')
>Bus ID | Day | Type | TotalNumberReservation
>1000 |Monday | Public | 1
>4000 |Monday | Public | 1

You can use the following which joins your tables on the bus id and then gets a count of the reservations:
select b.`bus id`,
b.day,
b.type,
count(r.date) TotalNumberReservation
from tblBus b
inner join tblReservation r
on b.`bus id` = r.`bus id`
where r.date = '2013-03-04'
and b.day = 'Monday'
group by b.`bus id`, b.day, b.type
See SQL Fiddle with Demo
If you want to return all rows that match the correct day even if there is not a reservation, then you will want to use a LEFT JOIN:
select b.`bus id`,
b.day,
b.type,
count(r.date) TotalNumberReservation
from tblBus b
left join tblReservation r
on b.`bus id` = r.`bus id`
AND r.date = '2013-03-04'
where b.day = 'Monday'
group by b.`bus id`, b.day, b.type
See SQL Fiddle with Demo

Here is the basic query to generate the counts for all busses, days, and dates that you can then filter as you need:
Select a.bus_id, day, type, count(*) as TotalNumberReservation
from tblBus a
join tblReservation b
on a.busId=b.busId
group by a.bus_id,day,type

Related

Sum columns with similar value- SQL

I need to sum all fields that have similar value.
I have a simple SQL query that give me back this result:
For example, the name like 'Climatizzazione' has to be sum to 'Climatizzatori Samsung' and 'Climatizzatori Daiki' and get a unique result.
The final result would be like that:
| name | totale_fatturato |
| -------- | -------------- |
| Climatizzazione | 535.241,583465|
| Scaldabagni| 90680,77684|
| Differenziali e Magnetotermici| 78511,185704|
ecc.......
This is my SQL query:
SELECT
cl.name,
SUM(od.total_price_tax_excl) AS totale_fatturato
FROM `ww_ps_order_detail` AS `od`
INNER JOIN `ww_ps_product` AS p ON od.product_id = p.id_product
INNER JOIN `ww_ps_category_lang` AS cl ON p.id_category_default = cl.id_category
WHERE od.ID_ORDER IN (
SELECT ID_ORDER
FROM ww_ps_orders
WHERE 1=1 AND DATE_ADD >= DATE_SUB(NOW(), INTERVAL 30 DAY)) AND cl.id_lang = 1
GROUP BY name
ORDER BY totale_fatturato DESC
LIMIT 10
What i have to do for get the result i want? Thx!
Thanks to Akina, Jonas Metzler and Trillion, i found my solution.
So, how you have suggest me, i create a supplementary column with some cases where i can handle all the exceptions and group by this column.
This is my result:
SELECT
cl.name AS NAME,
SUM(od.total_price_tax_excl) AS `totale_fatturato`,
CASE
WHEN cl.name LIKE 'Climatizza%' THEN 'Climatizzazione'
/* SOME OTHER CASES */
ELSE cl.name
END AS groupName
FROM `ww_ps_order_detail` AS `od`
INNER JOIN `ww_ps_product` AS p ON od.product_id = p.id_product
INNER JOIN `ww_ps_category_lang` AS cl ON p.id_category_default = cl.id_category
WHERE od.ID_ORDER IN (
SELECT ID_ORDER
FROM ww_ps_orders
WHERE 1=1 AND DATE_ADD >= DATE_SUB(NOW(), INTERVAL 30 DAY)) AND cl.id_lang = 1
GROUP BY groupName
ORDER BY totale_fatturato DESC

Group by Member but Order by Count Product

I want to display promos from all members in the order of the highest number of clicks in the last 1 week, terms that 1 member only displays 1 promo
like this:
id promo
member/sales
order by count
9
B
10
5
A
9
6
M
8
The following is the data table
Tabel Promo (product_promo)>> | ppo_id | ppo_sales | ppo_content |
Tabel click recording (ipslsprod) >> | idip | dipp (id promo) | mxd (datetime visit click)
Tabel sales (sales) >> | id | name |
And I've written down the code
SELECT pp.*,
s.*,
Count(ip.dipp) AS VIEWS
FROM product_promo pp
left join (SELECT *
FROM ipslsprod
WHERE mxd >= Date_sub(Now(), interval 7 day)) ip
ON ip.dipp = pp.ppo_id
left join sales s
ON pp.ppo_sales = s.id
GROUP BY pp.ppo_id
ORDER BY VIEWS DESC
But showing more than 1 member
id promo
member/sales
order by count
9
B
10
5
A
9
4
B
7
I've tried changing
GROUP BY pp.ppo_sales
The data is messy.
Please help and instructions,
I want to display each sales only 1 product_promo in the order of the highest number of ip.dipps.
You can use aggregation and window functions. I'm not sure exactly what the query is, but I think:
SELECT v.*
FROM (SELECT s.id, pp.id_product_promo, COUNT(*) AS views ,
ROW_NUMBER() OVER (PARTITION BY s.id ORDER BY COUNT(*) DESC) as seqnum
FROM sales s JOIN
product_promo pp
ON pp.ppo_sales = s.id JOIN
ipslsprod ip
ON ip.dipp = pp.ppo_id
WHERE ip.mxd >= DATE_SUB(NOW(),INTERVAL 7 day)) ip
GROUP BY s.id, pp.id_product_promo
) v
WHERE seqnum = 1;
Maybe this will enlighten a bit more:
SELECT your_fields, MAX(count_click) FROM [table] GROUP BY count_click ORDER BY count_click
From there you can add all the date related stuff to fine-tune the query.
Perhaps it is a good idea to read up on the MySQL INTERVAL for that.

Group_Concat with multiple joined tables

I have two main tables that comprise bookings for events.
A Registrants table (Bookings) R and an Events table E.
There are also two connected tables, Field_Values V and Event_Categories C
This diagram shows the relationship
What I am trying to do is create an Invoice query that mirrors the user's shopping cart. Often a user will book multiple events in one transaction, so my invoice should have columns for the common items e.g. User Name, User Email, Booking Date, Transaction ID and aggregated columns for the invoice line item values e.g. Quantity "1,2" Description "Desc1, Desc2" Price "10.00, 20.00" where there are two line items in the shopping cart.
The Transaction ID (dcea4_eb_registrant.transaction_id) is unique per Invoice and repeated per line item in that sale.
I have the following query which produces rows for each line item
SELECT
R.id as ID,
E.event_date as ServiceDate,
E.event_date - INTERVAL 1 DAY as DueDate,
Concat('Ad-Hoc Booking:',E.title) as ItemProductService,
Concat(R.first_name, ' ',R.last_name) as Customer,
R.first_name as FirstName,
R.last_name as LastName,
R.email,
R.register_date as InvoiceDate,
R.amount as ItemAmount,
R.comment,
R.number_registrants as ItemQuantity,
R.transaction_id as InvoiceNo,
R.published as Status,
E.event_date AS SERVICEDATE,
Concat('Ad-Hoc Booking:',E.title) AS DESCRIPTION,
R.number_registrants AS QUANTITY,
FORMAT(R.amount / R.number_registrants,2) AS RATE,
R.amount AS AMOUNT,
C.category_id as CLASS,
Concat(Group_Concat(V.field_value SEPARATOR ', '),'. ',R.comment) as Memo
FROM dcea4_eb_events E
LEFT JOIN dcea4_eb_registrants R ON R.event_id = E.id
LEFT JOIN dcea4_eb_field_values V ON V.registrant_id = R.id
LEFT JOIN dcea4_eb_event_categories C ON C.event_id = R.event_id
WHERE 1=1
AND V.field_id IN(14,26,27,15)
AND R.published <> 2 /*Including this line omits Cancelled Invoices */
AND R.published IS NOT NULL
AND (R.published = 1 OR R.payment_method = "os_offline")
AND (R.register_date >= CURDATE() - INTERVAL 14 DAY)
GROUP BY E.event_date, E.title, R.id, R.first_name, R.last_name, R.email,R.register_date, R.amount, R.comment
ORDER BY R.register_date DESC, R.transaction_id
This produces output like this
I'm using the following query to try to group together the rows with a common transaction_ID (rows two and three in the last picture) - I add group_concat on the columns I want to aggregate and change the Group By to be the transaction_id
SELECT
R.id as ID,
E.event_date as ServiceDate,
E.event_date - INTERVAL 1 DAY as DueDate,
Concat('Ad-Hoc Booking:',E.title) as ItemProductService,
Concat(R.first_name, ' ',R.last_name) as Customer,
R.first_name as FirstName,
R.last_name as LastName,
R.email,
R.register_date as InvoiceDate,
R.amount as ItemAmount,
R.comment,
R.number_registrants as ItemQuantity,
R.transaction_id as InvoiceNo,
R.published as Status,
Group_ConCat( E.event_date) AS SERVICEDATE,
Group_ConCat( Concat('Ad-Hoc Booking:',E.title)) AS DESCRIPTION,
Group_ConCat( R.number_registrants) AS QUANTITY,
Group_ConCat( FORMAT(R.amount / R.number_registrants,2)) AS RATE2,
Group_ConCat( R.amount) AS AMOUNT,
Group_ConCat( C.category_id) as CLASS,
Concat(Group_Concat(V.field_value SEPARATOR ', '),'. ',R.comment) as Memo
FROM dcea4_eb_events E
LEFT JOIN dcea4_eb_registrants R ON R.event_id = E.id
LEFT JOIN dcea4_eb_field_values V ON V.registrant_id = R.id
LEFT JOIN dcea4_eb_event_categories C ON C.event_id = R.event_id
WHERE 1=1
AND V.field_id IN(14,26,27,15)
AND R.published <> 2 /*Including this line omits Cancelled Invoices */
AND R.published IS NOT NULL
AND (R.published = 1 OR R.payment_method = "os_offline")
AND (R.register_date >= CURDATE() - INTERVAL 14 DAY)
GROUP BY R.transaction_id
ORDER BY R.register_date DESC, R.transaction_id
But this produces this output
It seems to be multiplying the rows. The Quantity column in the first row should just be 1 and in the second row it should be 2,1 .
I've tried using Group_Concat with DISTINCT but this doesn't work because often the values being concatenated are the same (e.g. the price for two events being booked are both the same) and the query only returns one value e.g. 10 and not 10, 10. The latter being what I need.
I'm guessing the issue is around the way the tables are joined but I'm struggling to work out how to get what I need.
Pointers in the right direction most appreciated.
You seem determined to go in what seems to me to be the wrong direction, so here's a gentle nudge down that hill...
Consider the following...
CREATE TABLE users
(user_id SERIAL PRIMARY KEY
,username VARCHAR(12) UNIQUE
);
INSERT INTO users VALUES
(101,'John'),(102,'Paul'),(103,'George'),(104,'Ringo');
DROP TABLE IF EXISTS sales;
CREATE TABLE sales
(sale_id SERIAL PRIMARY KEY
,purchaser_id INT NOT NULL
,item_code CHAR(1) NOT NULL
,quantity INT NOT NULL
);
INSERT INTO sales VALUES
( 1,101,'A',1),
( 2,103,'A',2),
( 3,103,'A',3),
( 4,104,'A',1),
( 5,104,'A',2),
( 6,104,'A',3),
( 7,103,'B',2),
( 8,103,'B',2),
( 9,104,'B',3),
(10,103,'B',2),
(11,104,'B',2),
(12,104,'B',1);
SELECT u.*
, x.sale_ids
, x.item_codes
, x.quantities
FROM users u
LEFT
JOIN
( SELECT purchaser_id
, GROUP_CONCAT(sale_id ORDER BY sale_id) sale_ids
, GROUP_CONCAT(item_code ORDER BY sale_id) item_codes
, GROUP_CONCAT(quantity ORDER BY sale_id) quantities
FROM sales
GROUP
BY purchaser_id
) x
ON x.purchaser_id = u.user_id;
+---------+----------+---------------+-------------+-------------+
| user_id | username | sale_ids | item_codes | quantities |
+---------+----------+---------------+-------------+-------------+
| 101 | John | 1 | A | 1 |
| 102 | Paul | NULL | NULL | NULL |
| 103 | George | 2,3,7,8,10 | A,A,B,B,B | 2,3,2,2,2 |
| 104 | Ringo | 4,5,6,9,11,12 | A,A,A,B,B,B | 1,2,3,3,2,1 |
+---------+----------+---------------+-------------+-------------+

Query: I have 4 rows, need to add the results from 3 rows into one, and leave the last row untouched

I have a kind of tricky question for this query. First the code:
SELECT user_type.user_type_description,COUNT(incident.user_id) as Quantity
FROM incident
INNER JOIN user ON incident.user_id=user.user_id
INNER JOIN user_type ON user.user_type=user_type.user_type
WHERE incident.code=2
GROUP BY user.user_type
What Am I doing?
For example, I am counting police reports of robbery, made from different kind of users. In my example, "admin" users reported 6 incidents of code "2" (robbery) and so on, as is showed in 'where' clause (incident must be robbery, also code 2).
this brings the following result:
+-----------------------+----------+
| user_type_description | Quantity |
+-----------------------+----------+
| Admin | 6 |
| Moderator | 8 |
| Fully_registered_user | 8 |
| anonymous_user | 9 |
+-----------------------+----------+
Basically Admin,Moderator and Fully_registered_user are appropriately registered users. I need to add them in a result where it shows like:
+--------------+------------+
| Proper_users | Anonymous |
+--------------+------------+
| 22 | 9 |
+--------------+------------+
I am not good with sql. Any help is appreciated. Thanks.
You can try to use condition aggregate function base on your current result set.
SUM with CASE WHEN expression.
SELECT SUM(CASE WHEN user_type_description IN ('Admin','Moderator','Fully_registered_user') THEN Quantity END) Proper_users,
SUM(CASE WHEN user_type_description = 'anonymous_user' THEN Quantity END) Anonymous
FROM (
SELECT user_type.user_type_description,COUNT(incident.user_id) as Quantity
FROM incident
INNER JOIN user ON incident.user_id=user.user_id
INNER JOIN user_type ON user.user_type=user_type.user_type
WHERE incident.code=2
GROUP BY user.user_type
) t1
You just need conditional aggregation:
SELECT SUM( ut.user_type_description IN ('Admin', 'Moderator', 'Fully_registered_user') ) as Proper_users,
SUM( ut.user_type_description IN ('anonymous_user') as anonymous
FROM incident i INNER JOIN
user u
ON i.user_id = u.user_id INNER JOIN
user_type ut
ON u.user_type = ut.user_type
WHERE i.code = 2;
Notes:
Table aliases make the query easier to write and to read.
This uses a MySQL shortcut for adding values -- just just adding the booelean expressions.
I would solve it with a CTE, but it would be better to have this association in a table.
WITH
user_type_categories
AS
(
SELECT 'Admin' AS [user_type_description] , 'Proper_users' AS [user_type_category]
UNION SELECT 'Moderator' AS [user_type_description] , 'Proper_users' AS [user_type_category]
UNION SELECT 'Fully_registered_user' AS [user_type_description] , 'Proper_users' AS [user_type_category]
UNION SELECT 'anonymous_user' AS [user_type_description] , 'Anonymous' AS [user_type_category]
)
SELECT
CASE WHEN utc.[user_type_category] = 'Proper_users' THEN
SUM(incident.user_id)
END AS [Proper_Users_Quantity]
, CASE WHEN utc.[user_type_category] = 'Anonymous' THEN
SUM(incident.user_id)
END AS [Anonymous_Quantity]
FROM
[incident]
INNER JOIN [user] ON [incident].[user_id] = [user].[user_id]
INNER JOIN [user_type] ON [user].[user_type] = [user_type].[user_type]
LEFT JOIN user_type_categories AS utc ON utc.[user_type_description] = [user_type].[user_type_description]
WHERE
[incident].[code] = 2

MySQL Join assistance

Hey guys I am struggling to create a query which gives schedule of a pilot for a given day. So far I've got
SELECT f.flight_date, l.lesson_date FROM Flight f JOIN lesson l ON f.pilot_idpilot = l.pilot_idpilot WHERE f.flight_date = CURDATE() OR l.lesson_date = CURDATE() AND pilot_idpilot = 7236;
The result I get is
Lesson_id | lesson_date | pilot_idpilot | idFlight | flight_date | pilot_id_pilot
Is there a way just to specify the type of activity the pilot is involved in e.g.
Activity | Date |
Any help would be awesome! thanks guys/girls
How about this:
SELECT 'Lesson' as Activity, lesson_date as Date
FROM Flight f JOIN lesson l ON f.pilot_idpilot = l.pilot_idpilot
WHERE l.lesson_date = CURDATE() AND pilot_idpilot = 7236
UNION
SELECT 'Flight' as Activity, flight_date as Date
FROM Flight
WHERE f.flight_date = CURDATE() AND pilot_idpilot = 7236;