MySQL Join assistance - mysql

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;

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

MySQL sum only new rows

I have a MySQL table with this format
transaction | user | amount | week
------------|---------|--------|------
1 | user_1 | 100 | 1
2 | user_2 | 50 | 1
3 | user_1 | 50 | 2
4 | user_3 | 200 | 2
I know how to calculate the sum amount for each week in MySQL, but is there a way in MySQL to calculate new users sum amount per week?
So for this table it would be:
week 1 = 150
week 2 = 200
Yes, there is. You can use the value of MIN(week) to indicate a particular user's first transaction.
SELECT w, SUM(amount)
FROM(
SELECT user, amount, MIN(week) AS w
FROM `trans`
GROUP BY user) newUserTrans
GROUP BY w
If you want to still show a week where there is no new user, then you can use this:
SELECT week, IFNULL(SUM(amount),0) AS total
FROM(
SELECT user, amount, MIN(week) AS w
FROM `trans`
GROUP BY user) newUserTrans RIGHT JOIN (SELECT DISTINCT week FROM trans) weeks ON newUserTrans.w = weeks.week
GROUP BY w
ORDER BY week
UPDATE:
Based on #skobaljic opinion, I also provide another alternative for the case when a user may have multiple records in the same week.
SELECT weeks.week AS Week, IFNULL(SUM(amount),0) AS Total
FROM(
SELECT trans.user, trans.amount, trans.week
FROM trans
JOIN (SELECT user, MIN(week) AS w
FROM trans
GROUP BY user) newWeek ON trans.user = newWeek.user
AND trans.week = newWeek.w) newUserTrans
RIGHT JOIN (SELECT DISTINCT week FROM trans) weeks ON newUserTrans.week = weeks.week
GROUP BY newUserTrans.week
ORDER BY weeks.week
Hope it helps.
I hope this could be helpful in any way:
select sum(A.`amount`) from `table` AS A WHERE A.`user` NOT IN (SELECT B.`user` FROM `table` AS B where A.`week` > B.`week') AND A.`week` = #pWeek
where #pWeek is a parameter with a particular number of a week
I think there is a better way of get the first week for a user.
First week is the minumum week for a user.
select
trans.week
,sum(amount) as amount
from trans
inner join
(select
user
,min(week) as firstweek
from
trans
group by
user
) as firstweek
on trans.user = firstweek.user
where
trans.week = firstweek.firstweek
group by
trans.week
$query = "SELECT * FROM [table] GROUP BY week";
this should work. I don't think you will need the sum(amount), but try it both ways.

MySQL Query To find Trains between two stations

My Train Details table,
Table Name- traindetailtb
Id Train_Number Train_Name From To
1 27658 Venad Express ABC XYZ
2 27659 Venad Express XYZ ABC
and my Train Days Table,
Table Name- traindaystb
Id Train_Number Days
1 27658 Sunday
2 27658 Wednesday
3 27659 Saturday
4 27659 Friday
and this my Train Schedule Table,
Table Name- scheduletb
Id Train_Number Station Time
1 27658 ABC 09:00am
2 27658 CDE 10:00am
3 27658 XYZ 11:00am
4 27659 XYZ 12:00pm
5 27659 CDE 01:00pm
6 27659 ABC 02:00pm
There will be two input, From and To
I need a query that gives all Trains(ie,Train_Number,Train_Name,Days) between the given stations
For eg:
For input From- CDE To-XYZ ---->
output will be-- 27658 Venad Express S W
and For input From- XYZ To-CDE ---->
output will be-- 27659 Venad Express M T
Can anyone Please help me to do this.
Are you looking for something like this?
SELECT q.train_number, MAX(t.train_name) train_name, GROUP_CONCAT(LEFT(d.days, 1)) days
FROM
(
SELECT s.train_number
FROM scheduletb s JOIN scheduletb e
ON s.train_number = e.train_number
WHERE s.station = 'CDE' -- from
AND e.station = 'XYZ' -- to
AND s.id < e.id
) q JOIN traindaystb d
ON q.train_number = d.train_number JOIN traindetailtb t
ON q.train_number = t.train_number
GROUP BY q.train_number
Output for CDE -> XYZ:
| TRAIN_NUMBER | TRAIN_NAME | DAYS |
|--------------|---------------|------|
| 27658 | Venad Express | S,W |
Output for XYZ -> CDE:
| TRAIN_NUMBER | TRAIN_NAME | DAYS |
|--------------|---------------|------|
| 27659 | Venad Express | S,F |
Here is SQLFiddle demo
You can try somthing like this:-
SELECT A.Train_number, A.Train_name, C.days
FROM traindetailtb A, traindaystb B, scheduletb C
WHERE C.Train_Number = A.Train_Number
AND A.Train_Number = B.Train_Number
AND FROM = 'ABC' AND TO = 'XYZ';
This might help you.
Try this
SELECT t.Train_Number,t.Train_Name,d.Days
from traindetailtb t,traindaystb d
WHERE
t.Train_Number=d.Train_Number AND From='ABC' AND To='XYZ';
and just read the input and put it into the from=' ' and to=' ';
this single query will return both the output?
i suggest as follow :
select
traindetailtb.Train_Number,
traindetailtb.Train_Name,
traindetailtb.From,
traindetailtb.To,
tranddaystb.Days,
scheduletb.Time
From
traindetailtb
join trandaystb on
traindetailtb.Train_Number=traindaystb.Train_Number
join scheduletb on
traindetailtb.Train_Number=scheduletb.Train_Number and
traindetailtb.From=scheduletb.From
where
traindetailtb.From=$inputFrom
and
traindetailtb.To=$inputTo
Using a self join you can do this, assuming that the Time is really a time field
SELECT a.Train_Number, d.Train_Name, GROUP_CONCAT(e.Days)
FROM scheduletb a
INNER JOIN scheduletb b
ON a.Train_Number = b.Train_Number
AND b.Time > a.Time
INNER JOIN traindetailtb d
ON a.Train_Number = d.Train_Number
INNER JOIN traindaystb e
ON a.Train_Number = e.Train_Number
WHERE a.Station = 'CDE'
AND b.Station = 'XYZ'
GROUP BY a.Train_Number, d.Train_Name
assuming that you have a real time field for the time
If you wanted only the trains that went directly from CDE to XYZ with no intermediate stations you could add a LEFT OUTER JOIN to the table looking for stations with a time between the other 2:-
SELECT a.Train_Number, d.Train_Name, GROUP_CONCAT(e.Days)
FROM scheduletb a
INNER JOIN scheduletb b
ON a.Train_Number = b.Train_Number
AND b.Time > a.Time
LEFT OUTER JOIN scheduletb c
ON a.Train_Number = c.Train_Number
AND c.Time > a.Time
AND c.Time < b.Time
INNER JOIN traindetailtb d
ON a.Train_Number = d.Train_Number
INNER JOIN traindaystb e
ON a.Train_Number = e.Train_Number
WHERE a.Station = 'CDE'
AND b.Station = 'XYZ'
AND c.Station IS NULL
GROUP BY a.Train_Number, d.Train_Name
If you want to visualize the days in one single cell instead of spread into multiple rows, use GROUP_CONCAT, which acts as a aggregator-function.
select tde.train_number, tde.train_name, GROUP_CONCAT(tda.days, ",") as days
from traindetailtb tde
join traindaystb tda on tda.train_number=tde.train_number
where tde.from = $user_input_from
and tde.to = $user_input_to
group by tde.train_number, tde.train_name

Mysql query left join access to variable

If someone can help me with this one I've got these tables And I would like to get all bookings between two dates, and to know whether any of it is done by someone else or it is fail.
Table:Bookings
id | date | date_end | repeat | day_of_week | user_id | price
---------------------------------------------------------------------
1 2013-07-01 0000-00-00 1 3 1 20
2 2013-07-16 0000-00-00 1 -1 1 10
Table:Bookings_done_by_other
id | date | user_id | booking_id
---------------------------------
1 2013-07-01 2 2
2 2013-07-13 2 2
Table:Bookings_fail
id | date | booking_id
---------------------------
1 2013-07-01 2
2 2013-07-11 2
Table:Tally
id
--
1
....
500
Here is my query which is working well, but I can't manage with it to give me all what I want.
SELECT f.date as fail, b.id, b.date, a.showdate, DATEDIFF(b.date, a.showdate) AS diff
FROM bookings as b
LEFT JOIN bookings_fail f ON (b.id = f.booking_id and DATE(f.date) = DATE(a.showdate) )
,
(
SELECT DATE_ADD('2013-07-01 00:00:00',INTERVAL Id DAY) as showdate
FROM `tally`
WHERE (DATE_ADD('2013-07-01 00:00:00',INTERVAL Id DAY) <= '2013-07-20 00:00:00')
ORDER BY Id ASC
) a
WHERE
MOD(DATEDIFF(b.date, a.showdate), b.repeat) = 0
AND
DATE(a.showdate)>= DATE(b.date)
when is like this is throw error that cant see a.showdate in left join, when I move the left join next to "a" table is throw error that cant see b.id so Is there any way to get this join working?
I would like to get result something like this
id | showdate | fail | by_other |
-----------------------------
1 2013-07-01 NULL 2
2 2013-07-01 1 NULL //Or date
1 2013-07-03 NULL NULL
1 2013-07-04 NULL NULL
1 2013-07-05 NULL NULL
1 2013-07-06 NULL NULL
.............................
1 2013-07-20 NULL NULL
Sorry if My English is not too good, and Thanks in advance to everyone who can help.
Here some pictures hope is getting clear I cant explain what I want properly
This is bookings
Booking table
This is fail
Fail table
I cant put more than 2 links so that's why these two are just like text
so what's happening when I want to get my bookings for some date I do this
s16.postimg.org/l00k1math/image.jpg
What I want to have done is
s12.postimg.org/5o5hbnmdp/image.jpg
But not only for booking with id 1 I wont to be b.id = un.booking_id and then if there is record for fail to appear how is on the last picture
Thanks for your patience
I think I finally understand what you are trying to do. My suggestion is to format your query like this:
SELECT b.id, a.showdate, f.id as fail, o.id as other
FROM (
SELECT DATE_ADD('2013-07-01 00:00:00',INTERVAL Id DAY) as showdate
FROM `tally`
WHERE (DATE_ADD('2013-07-01 00:00:00',INTERVAL Id DAY) <= '2013-07-20 00:00:00')
ORDER BY Id ASC
) a
LEFT JOIN Bookings b ON (
MOD(DATEDIFF(b.date, a.showdate), b.repeat) = 0 AND
DATE(a.showdate)>= DATE(b.date)
)
LEFT JOIN Bookings_fail f ON (
b.id = f.booking_id AND
DATE(f.date) = DATE(a.showdate)
)
LEFT JOIN Bookings_done_by_other o ON (
b.id = o.booking_id AND
DATE(o.date) = DATE(a.showdate)
)
You start by selecting from the generated a table, and join that with the Bookings table. Once you have those two joined it's easy to join any other tables based on the a.showdate and the b.id fields.
I've created a SQL Fiddle example, more or less based on your data, so you can see how it works. http://sqlfiddle.com/#!2/7e151/1

Correct SQL statement needed in my scenario

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