mysql query find between past dates and current dates - mysql

I have two tables one is simple like this named orders and due_dates
id | name | price | due_id | status
1 a 10 1 0
2 b 20 1 0
3 c 30 1 1
4 d 40 2 0
4 d 40 2 1
and an other table with dates
id | start_date | end_date
1 2011-04-01 2011-05-21
2 2011-07-01 2011-07-15
what I am trying to find is all orders from past period with status 0 and from the current period all records with status 0 and 1 i know how to get orders from current period
SELECT *
FROM orders
INNER JOIN due_dates ON orders.due_id = due_dates.due_id
AND now() BETWEEN due_dates.start_date AND due_dates.end_date
AND status in (0,1);

SELECT *
FROM orders
INNER JOIN due_dates ON orders.due_id = due_dates.due_id
WHERE
(status in (0,1) and now() BETWEEN due_dates.start_date AND due_dates.end_date) OR
(status = 0 AND due_dates.end_date < now())

Related

MySQL Conditional SELECT in SELECT

Table:
id price is_active
========================
1 20.99 0
2 10.99 1
3 30.99 0
4 15.99 1
5 35.99 1
I am trying to select COUNT of all rows that has is_active equals to 1, so I've used this simple query:
SELECT COUNT(*) FROM table WHERE is_active=1
But what if I want to also know how many rows have price:
less than 15
between 15 and 30
more than 30
I can write this:
SELECT COUNT(*) FROM table WHERE is_active=1 AND price < 15
SELECT COUNT(*) FROM table WHERE is_active=1 AND price > 15 AND price < 30
SELECT COUNT(*) FROM table WHERE is_active=1 AND price > 30
But can I do it in one simple query that returns something like this?
"Less than 15" | "Between 15 and 30" | "More than 30"
1 | 2 | 2
With conditional aggregation:
SELECT
SUM(price < 15) `Less than 15`,
SUM(price >= 15 AND price <= 30) `Between 15 and 30`,
SUM(price > 30) `More than 30`
FROM `table`
WHERE is_active=1
In MySql a boolean expression like price < 15 is evaluated as 0 for false or 1 for true.
See the demo.
Results:
| Less than 15 | Between 15 and 30 | More than 30 |
| ------------ | ----------------- | ------------ |
| 1 | 1 | 1 |
Because they are even intervals you could
SELECT
IF(price > 30, 30, price) div 15 as g,
count(*) as c
FROM `table`
WHERE is_active=1
GROUP BY g
Note this leaves 30 in the 'more than 30' category

How to LEFT JOIN more than 2 tables to get no records?

I want to get the date of this week and the total sum of total_price even there is no transaction on the specific date. The problem is when I change the value of tbl_barangay.city_id into 2, all the data of tbl_barangay.city_id = 1 is included. I want to get all records according to the value of tbl_barangay.city_id. How can I left join more than 2 tables so I can get the expected data?
Sample data
tbl_calendar tbl_city tbl_tran
date_id date city_id city_name tran_id tran_date city_id
1 2019-08-19 1 Sala 1 2019-08-19 1
2 2019-08-20 2 Marinig 2 2019-08-20 1
3 2019-08-21 3 Pulo 3 2019-08-23 2
4 2019-08-22
5 2019-08-23
6 2019-08-24
7 2019-08-25
tbl_tran_details
detail_id item total_price tran_id
1 Item1 20 1
2 Item2 20 1
2 Item3 30 2
2 Item1 30 3
Expected data if the tbl_city.city_id = 1
Date Total
2019-08-19 40
2019-08-20 30
2019-08-21 0
2019-08-22 0
2019-08-23 0
2019-08-24 0
and if the tbl_city.city_id = 2
Date Total
2019-08-19 0
2019-08-20 0
2019-08-21 0
2019-08-22 0
2019-08-23 30
2019-08-24 0
SELECT tbl_calendar.date Date,
SUM(IFNULL(tbl_tran_details.total_price,0)) Total FROM tbl_calendar
LEFT JOIN
tbl_tran ON tbl_calendar.date = tbl_tran.tran_date
LEFT JOIN
tbl_tran_details ON tbl_tran.tran_id = tbl_tran_details.tran_id
LEFT JOIN
tbl_city ON tbl_tran.city_id = tbl_city.city_id AND tbl_city.city_id = 2
WHERE
YEAR(tbl_calendar.date) = YEAR(NOW())
AND
WEEK(tbl_calendar.date) = WEEK(NOW())
GROUP BY
tbl_calendar.date
The problem is that you filter the cities in the wrong table because you want to get the sum of transactions for a certain city from the tbl_tran table, but you filter the cities in the tbl_city - which you do not even use in this query.
...
FROM (tbl_calendar
LEFT JOIN
tbl_tran ON tbl_calendar.date = tbl_tran.tran_date AND tbl_tran.city_id = 2)
LEFT JOIN
tbl_tran_details ON tbl_tran.tran_id = tbl_tran_details.tran_id
...

mysql - How to query for items sold within 12 months of each other

I've got a table of sales transactions and I've been asked to report only on items that have two sales within a 12 month period. For example:
id | Item | Sale Date
---------------------
1 | A | 2017-02-03
2 | C | 2016-05-04
3 | A | 2016-08-23
4 | B | 2016-03-25
5 | D | 2015-07-30
6 | A | 2013-04-19
7 | E | 2011-03-12
8 | B | 2017-05-20
9 | E | 2011-05-04
Item A has three sales records, but only transactions 1 & 3 should be returned as transaction 6 is more than 12 months from transaction 3.
Item B has two sales, but greater than 12 months apart so should be excluded.
Item E has two sales within 12 months of each other so should be included.
I'm using this to find entries with multiple sales:
SELECT * FROM salesdata.sales
INNER JOIN
(SELECT Item_Code, COUNT(*) c from salesdata.sales
GROUP BY Item_Code HAVING c > 1) as vals
ON sales.Item_Code = vals.Item_Code;
But can't figure out how to test if the two sales for an item are within 12 months of each other.
SELECT DISTINCT x.*
FROM my_table x
JOIN my_table y
ON y.id <> x.id
AND y.item = x.item
AND DATEDIFF(GREATEST(y.sale_date,x.sale_date),LEAST(y.sale_date,x.sale_date)) < 365;
You can get a list of items that have had a sale within the previous 12 months:
select s.*
from salesdata.sales s
where exists (select 1
from salesdata s2
where s2.item_code = s.item_code and
s2.sale_date >= s.sale_date - interval 1 year and
s2.sale_date < s.sale_date
);
Your question is unclear what you want to do with this information, but this retrieves all items.
SELECT s.*
from salesdata.sales s
INNER JOIN (
SELECT COUNT(item), item
FROM salesdata.sales
WHERE Sale Date >= DATEADD(year, -1, GETDATE())
GROUP BY item
HAVING COUNT(item) > 1
) b
on s.item = b.item
and s.Sale Date >= DATEADD(year, -1, GETDATE())

Getting Max date from multiple table after INNER JOIN

I have two following tables
table 1)
ID | HOTEL ID | NAME
1 100 xyz
2 101 pqr
3 102 abc
table 2)
ID | BOOKING ID | DEPARTURE DATE | AMOUNT
1 1 2013-04-12 100
2 1 2013-04-14 120
3 1 2013-04-9 90
4 2 2013-04-14 100
5 2 2013-04-18 150
6 3 2013-04-12 100
I want to get reault in mysql such that it take the row from table two with MAX DEPARTURE DATE.
ID | BOOKING ID | DEPARTURE DATE | AMOUNT
2 1 2013-04-14 120
5 2 2013-04-18 150
6 3 2013-04-12 100
SELECT b.ID,
b.BookingID,
a.Name,
b.departureDate,
b.Amount
FROM Table1 a
INNER JOIN Table2 b
ON a.ID = b.BookingID
INNER JOIN
(
SELECT BookingID, MAX(DepartureDate) Max_Date
FROM Table2
GROUP BY BookingID
) c ON b.BookingID = c.BookingID AND
b.DepartureDate = c.Max_date
SQLFiddle Demo
Well,
SELECT * FROM `table2` ORDER BY `DEPARTURE_DATE` DESC LIMIT 0,1
should help

Showing today's current rank and yesterday's

I have a table with IDs, rank, chart_date, and pageviews. It's based on a cron job that is run nightly and compiles the number of pageviews for that ID.
For instance:
ID | RANK | PAGEVIEWS | CHART_DATE
5 1 100 2012-10-14
9 2 75 2012-10-14
13 3 25 2012-10-14
9 1 123 2012-10-13
5 2 74 2012-10-13
19 3 13 2012-10-13
So I'm grabbing today's chart based on 2012-10-14 and ranking the data by 1-3. But I also want to show the rank where the ID was on the previous date.
For instance, on 2012-10-14 ID 5 was ranked 1 but on 2012-10-13 it was ranked 2.
Can I do this with one query? Or do I have to loop thru the results based on today and do a query for each ID?
Can I do this with one query?
You can, but you need a JOIN between the table with today's date and the table with yesterday's date:
SELECT today.*, yesterday.rank
FROM yourtable AS today
JOIN yourtable AS yesterday
ON (today.id = yesterday.id
AND today.chart_date = date(now())
AND yesterday.chart_date = date(date_sub(now(), interval 1 day))
)
ORDER BY today.rank DESC;
You can even show the difference:
SELECT today.*, yesterday.rank AS yest, yesterday.rank-today.rank AS incr
FROM yourtable AS today
LEFT JOIN yourtable AS yesterday
ON (today.id = yesterday.id
AND today.chart_date = date(now())
AND yesterday.chart_date = date(date_sub(now(), interval 1 day))
)
ORDER BY today.rank DESC;
ID | RANK | PAGEVIEWS | CHART_DATE | YEST | INCR
5 1 100 2012-10-14 2 | 1
9 2 75 2012-10-14 1 | -1
13 3 25 2012-10-14 4 | 1
(LEFT JOIN ensures today's data is there even if yesterday's isn't).
Untested but something like this should work:
select today.id, today.rank, yesterday.rank
from mytable as today
left join mytable as yesterday on today.id = yesterday.id
where today.chart_date = 2012-10-14
order by pageviews desc limit 3