Mysql join query failure - mysql

For the tables below I need to output the rows that are not in the member_booking table from master_vehicle_inventory table.
I also need the results from master_vehicle_inventory which don't fall between the range of mb_startdate and mb_returndate.
master_vehicle_inventory table
mvi_id
1
2
3
4
member_booking table
mb_id mb_startdate mb_returndate mvi_id
100 22-04-2016 30-04-2016 2
101 23-01-2016 02-05-2016 3
So far I have tried this:
SELECT
mb.mb_id,
mb.mb_startdate,
mb.mb_returndate,
mvi.mvi_id
FROM master_vehicle_inventory AS mvi LEFT JOIN LEFT
JOIN member_booking AS mb ON mvi.mvi_id = mb.mvi_id
WHERE CURDATE() NOT BETWEEN mb.mb_startdate
AND mb.mb_returndate
AND mvi.mvi_id NOT IN (SELECT mvi.mvi_id
FROM member_booking)
But it doesn't give the results want.

To return rows from `master_vehicle_inventory` which do not have a "matching" row in `member_booking` table, we can use an anti-join pattern.
Assuming \mb_startdate` and `mb_enddate` are defined as datatype DATE.
Something like this:
SELECT mvi.mvi_id
FROM master_vehicle_inventory mvi
LEFT
JOIN member_booking mb
ON mb.mvi_id = mvi.mvi_id
AND mb.mb_startdate <= DATE(NOW())
AND mb.mb_enddate > DATE(NOW())
WHERE mb.mvi_id IS NULL
(The specification for a "matching" row is a bit vague.)
Given DATE(NOW()) returns '2016-04-25' we expect that query to return rows
mvi_id
------
1
4
(We are suspicious that the datatype of the columns may not be DATE because the values shown in the example data are not in the YYYY-MM-DD format we expect returned for a DATE expression.)

Related

Minus the value based on data using MySQL

I've the following data.
What I need like below
I need to minus order by 1 with 2.
Example : (1-2) and I've display the result in order by 3.
If the branch having order_by as 1 - display as it is.
Using MySQL, how can I get this result?
You can get this result with a UNION query. The first part selects all rows from your table, the second uses a self-join to find branches which have order_by values of both 1 and 2, and subtracts their due values to get the new due value:
SELECT *
FROM data
UNION ALL
SELECT 3, d1.branch, d1.due - d2.due
FROM data d1
JOIN data d2 ON d2.branch = d1.branch AND d2.order_by = 2
WHERE d1.order_by = 1
ORDER BY branch, order_by
Demo on dbfiddle

How can I do a table join where the composite key is an access number and a date +/- 1 day

I am trying to do a table join where the composite key is an access number and a snapshot date, and the data of interest is Status. Here's what the simple join looks like:
SELECT A.Access_Num, B.Access_Num, A.SNAPSHOT_DATE, B.SNAPSHOT_DATE, B.Status
FROM A
INNER JOIN B
ON A.Access_Num = B.Access_Numb AND A.SNAPSHOT_DATE = B.SNAPSHOT_DATE
My obstacle is that the data of interest Status is not populated on the exact match for SNAPSHOT_DATE (20% of the time). Sometimes it varies by +/- 1 from the SNAPSHOT_DATE in table A. There's still a record match, but table B will just return NA.
I am trying to write a join case that examines if Status returns as NA, to look at a composite key from the previous day for Table_B, and a composite key from the next day to see if there's a valid value available (i.e., not NA).
In the table below, I would want the query to recognize that row 3 returns an NA, so then it looks at the previous or next day to find a valid value. It should pick up that row 4 has a non-NA value, and return that one.
Row A.Access_Num B.Access_Num A.SNAPSHOT_DATE B.SNAPSHOT_DATE B.STATUS
1 11 11 12-12-2018 12-12-2018 Y
2 11 11 12-13-2018 12-13-2018 Y
3 13 13 12-05-2018 12-05-2018 NA
4 13 13 12-06-2018 Y
You can use inequalities in the ON clause:
SELECT A.Access_Num, B.Access_Num, A.SNAPSHOT_DATE, B.SNAPSHOT_DATE, B.Status
FROM A INNER JOIN
B
ON A.Access_Num = B.Access_Numb AND
A.SNAPSHOT_DATE >= B.SNAPSHOT_DATE - INTERVAL 1 DAY AND
A.SNAPSHOT_DATE <= B.SNAPSHOT_DATE + INTERVAL 1 DAY ;

How to retrieve Closest date from another table dynamically MySQL

I have two tables:
INFO table
ID LockDate Investor
157 10/15/2018 TEST1
VF1 09/02/2018 TEST2
LO2 05/01/2018 TEST3
09K 03/03/2012 TEST4
098 05/01/2012 TEST5
099 09/09/2012 TEST6
2YT 08/25/2012 TEST7
NUMBERS table
Dates Amount
10/10/2018 25.10
08/31/2018 200.15
05/10/2018 15.251
03/03/2012 10.10
05/10/2012 15.251
08/31/2012 548.0
I want the query to select all the values in the INFO table and find the closest or equal date in the Numbers table and give me the Amount. So my results would be:
ID LockDate Investor Amount
157 10/15/2018 TEST1 25.10
VF1 09/02/2018 TEST2 200.15
LO2 05/01/2018 TEST3 15.251
09K 03/03/2012 TEST4 10.10
098 05/01/2012 TEST5 15.251
099 09/09/2012 TEST6 548.0
2YT 08/25/2012 TEST7 548.0
By closest I mean equal or closest one whether it is lesser or greater than lock date.
This is the query I'm using but it is just retrieving the greater or equal one which doesn't work at all for me since I have to do it dynamically...
SELECT I.* ,
N.Amount FROM
(
SELECT A.*, MIN(NUM.Dates) AS XDATE
FROM INFO A
INNER JOIN NUMBERS AS NUM
ON NUM.Dates >= A.LockDate
GROUP BY A.ID
)AS RES
INNER JOIN NUMBERS AS N
ON N.Dates = I.XDATE
I will appreciate any help.
You just need to find the absolute minimum value for LockDate minus Dates. This will give you the closest date; lesser or greater. Rest is easy.
SELECT info.*, numbers.*
FROM info
INNER JOIN (
SELECT ID, MIN(DATEDIFF(GREATEST(LockDate, Dates), LEAST(LockDate, Dates))) Delta
FROM info
CROSS JOIN numbers
GROUP BY ID
) g ON info.ID = g.ID
INNER JOIN numbers ON DATEDIFF(GREATEST(LockDate, Dates), LEAST(LockDate, Dates)) = g.Delta
SQL Fiddle
Not sure what is your definition of "closest".
Here is my approach to get dates<=LockDate
http://sqlfiddle.com/#!9/8eea46/8
SELECT i.*, n.amount
FROM info i
LEFT JOIN numbers n
ON i.LockDate >= n.dates
LEFT JOIN numbers n_all
ON i.LockDate >= n_all.dates
AND n_all.dates > n.dates
WHERE n_all.dates IS NULL
Note: expected result is different since the definition of "closest" kind changed.
PS
Q: Why do I think that is a good approach?
A: Because whenever we deal with the data related to the timeline usually we expect data to know what (state, events, results) was before the moment we have on the timeline but not what will happen in future. That mean 31/12/2017 line/record can have/collect data from any table/records before 31/12/2017 but none from 2018. This strategy helps to keep reports consistent. They less dependent on the date when we generate the report. if we generate report about Dec 2017 at 1st Jan 2018 it will output same result as if we generate same report on same period Dec 2017 but week or month later 10th Jan 2018 or 1st of Feb.

SQL Select data from table when date is either specified or empty

I want to select data from my database when a particular column in a table has a specific data or it is not filled.
here is my sql code:
SELECT
bus.bus_id,
bus.seats,
entity.entityid,
entity.company_name,
entity.logo AS companylogo,
route.start_point,
route.drop_point,
route.boarding_time,
route.arrival_time,
FROM
loading_buses
INNER JOIN bus ON loading_buses.bus_id = bus.bus_id
INNER JOIN route ON loading_buses.route_id = route.route_id
INNER JOIN entity ON bus.entity = entity.entityid AND route.entity_id =
entity.entityid
WHERE
loading_buses.`current_date` ='23/1/2018' OR
loading_buses.`current_time` >= '00:00' AND
route.start_point = 'accra' AND
route.drop_point = 'kumasi'
ORDER BY
route.price ASC
And this is my output
SQL OUTPUT
1 49 1 STC assets/images/stc.png accra kumasi 1/17/2018 20:00 1/18/2018 00:00 20 9/18/2017 7/18/2017
2 15 1 STC assets/images/stc.png accra kumasi 1/17/2018 20:00 1/18/2018 00:00 20 9/18/2017 7/18/2017
3 55 1 STC assets/images/stc.png accra kumasi 1/17/2018 20:00 1/18/2018 00:00 20 9/18/2017 7/18/2017
In my database, the column current date is has certain date which must show depending on the date inserted or if no date in the column, it must show.
So in conclusion, result from the query show show only data for the specified date and null. But Query is displaying all data in the table
current_date is used as keyword to define system date in many databases. So, please make sure It is not the case here.
current_date ='23/1/2018' --- Change date value in this condition and see if it still returns all the data.
Also, comment out this condition --- loading_buses.current_time >= '00:00'
as all the rows satisfy this condition.
if you want check for null you should use is null
WHERE loading_buses.`current_date` ='23/1/2018' OR
loading_buses.`current_time` is null
Or based on your comment you can use
WHERE loading_buses.`current_date` ='23/1/2018' AND
loading_buses.`current_time` is null
You have to use () to group your OR's:
WHERE
(loading_buses.`current_date` ='2018-01-23' OR loading_buses.`current_date` is null)
AND
route.start_point = 'accra' AND
route.drop_point = 'kumasi'

Calculate running day difference in MySQL

I'd like tot calculate the difference in days from the current row, compared to the previous row. What I have now:
Here is my column is day difference
**Day_Diff**
351
363
363
But what I actually want:
**Day_Diff**
351
12
12
What query would I need to accomplish this?
This should do the work (if what you want is minimum in first row and then difference to the minimum, with table being the name of your table and day_diff the name of the column you named Day_diff):
See sqlfiddle :
SELECT
CASE WHEN t1.day_diff = t2.min_day_diff
THEN t1.day_diff
ELSE t1.day_diff - t2.min_day_diff
END
FROM mytable t1
LEFT JOIN (SELECT MIN(day_diff) AS min_day_diff FROM mytable) t2
ON True;