I have one problem that I can't resolve.
I have 2 tables.
Table 1:
ID | Time
1 | 08:12:54
2 | 08:15:40
3 | 09:30:01
4 | 10:15:15
5 | 10:56:12
6 | 11:00:03
Table 2:
ID | Name| Previous | Current
1 | Queue | null | 11
2 | Queue | 11 | 19
3 | Queue | 19 | 11
3 | List | null | 11
4 | Queue | 11 | 16
4 | List | null | 11
5 | Queue | null | 15
6 | Queue | 15 | 19
The result wanted:
NumberQueue | Start | End
11 | 08:12:54 | 08:15:40
19 | 08:15:40 | 09:30:01
11 | 09:30:01 | 10:15:15
15 | 10:56:12 | 11:00:03
...
...
The previous and the current fields, have the number of the Queue and I want to know for each Queue, the start date and the end date, knowing that the previous has the previous Queue, and the current has the new Queue.
I want one query that can present this result. Help me. :(
Regards.
SELECT t1outer.ID, t1outer.Time AS start, (
SELECT Time FROM Table1 AS t1inner
WHERE t1inner.ID > t1outer.ID
ORDER BY ID ASC LIMIT 1
) AS end, Table2.Previous, Table2.Current
FROM Table1 AS t1outer
LEFT JOIN Table2 USING (ID);
This select statement should provide the information you need:
SELECT Current AS Number, t1out.Time AS Start, (
SELECT Time FROM Table1 AS t1in
WHERE t1in.ID > t1out.ID
ORDER BY ID ASC LIMIT 1
) AS End FROM Table2
LEFT JOIN Table1 AS t1out USING (ID)
WHERE Table2.Name = 'Queue';
Related
Having a hard time wrapping my mind around what seems should be a simply query.
So let's say we have a table that keeps track of amount of widgets/balloons in each store by date. How would you get a list of stores and their latest widget/balloons count?
i.e.
mysql> SELECT * FROM inventory;
+----+------------+-------+---------+---------+
| id | invDate | store | widgets | balloons|
+----+------------+-------+---------+---------+
| 1 | 2011-01-01 | 3 | 50 | 35 |
| 2 | 2011-01-04 | 2 | 50 | 35 |
| 3 | 2013-07-04 | 3 | 12 | 78 |
| 4 | 2020-07-04 | 2 | 47 | 18 |
| 5 | 2020-08-06 | 2 | 16 | NULL |
+----+------------+-------+---------+---------+
5 rows in set (0.00 sec)
Would like the result table to list all stores and their latest inventory of widgets/baloons
store, latest widgets, latest balloons
+-------+-----------+---------+
| store | widgets | baloons |
+-------+-----------+---------+
| 2 | 16 | NULL |
| 3 | 12 | 78 |
+-------+-----------+---------+
or grab latest non NULL value for balloons.
This works for all versions of MySQL
select i.*
from inventory i
join
(
select store, max(invDate) as maxDate
from inventory
group by store
) tmp on tmp.store = i.store
and tmp.maxDate = i.invDate
With MySQL 8+ you can do window functions:
with cte as
(
select store, widgets, balloons,
ROW_NUMBER() OVER(PARTITION BY store ORDER BY invDate desc) AS rn
from inventory
)
select * from cte where rn = 1
You can use a correlated sub query to get latest record for each store
select i.*
from inventory i
where i.invDate = (
select max(invDate)
from inventory
where i.store = store
)
order by i.store
DEMO
I have a query between two tables.
First table is a list of users
+----+-------+-----------+
| id | name | expire_on |
+----+-------+-----------+
| 22 | JOHN | (null) |
| 44 | SMITH | (null) |
| 55 | DOE | 5 |
+----+-------+-----------+
Where "expire_on" can be NULL, but if compiled it is the expire of his subscription, in days.
And I have a list of transactions:
+----+----------------+-----------------+--------------+-------------+----------------------+
| id | id_member_card | amount_original | amount_final | description | utc_date_t |
+----+----------------+-----------------+--------------+-------------+----------------------+
| 1 | 22 | 12 | 12 | (null) | 2017-05-01T10:11:12Z |
| 2 | 22 | 50 | 50 | (null) | 2018-02-01T10:20:30Z |
| 3 | 44 | 7 | 7 | (null) | 2018-02-02T07:50:40Z |
| 4 | 22 | 9 | 9 | (null) | 2018-03-01T10:00:14Z |
| 5 | 44 | 5 | 5 | (null) | 2018-03-03T08:09:10Z |
| 6 | 22 | 0 | 0 | RENEW | 2018-05-02T11:22:33Z |
| 7 | 55 | 12 | 12 | (null) | 2018-05-03T10:20:30Z |
+----+----------------+-----------------+--------------+-------------+----------------------+
I have this starting points:
1) The user "expires" after 365 days of his very first transaction. The id 44 will expire on the 02-02-2019... > BUT >
2) If the user has a field "expire_on", he expires after the X days and not anymore the 365. In my example, id 55 is expired on the 07-05-2018.
3) If in the transaction list there is a RENEW, the user expires 365 days after this transaction renew and not anymore from the first one. Id 22 will expire only on the 02-05-2019 (pratically, we could consider a RENEW transaction as his first_transaction, if this can help to write a smarter query ) > BUT
If the user has the expire_on set, he expires X days after this renew (if the id 22 had expire_on set on, for example, let's say, 10 days, he would be expired on 12-05-2018 and not anymore 02-05-2019).
I hope that I'm clear.
Now MySql query, that I cannot complete considering the RENEW or not.
First of all, this is the link to the fiddle: http://sqlfiddle.com/#!9/16a3a/1
And this is the query:
SELECT member_card.id AS id,
member_card.name,
member_card.expire_on,
ts1.* FROM member_card
INNER JOIN (
SELECT member_card.id,
MIN(transaction.utc_date_t) AS first_transaction,
MAX(transaction.utc_date_t) AS last_transaction,
IFNULL (
DATE(DATE_ADD(MAX(transaction.utc_date_t), INTERVAL expire_on DAY)) ,
DATE(DATE_ADD(MAX(transaction.utc_date_t), INTERVAL 365 DAY))
)
AS final_expire ,
SUM(transaction.amount_final) AS balance
FROM transaction
INNER JOIN member_card ON transaction.id_member_card = member_card.id
GROUP BY member_card.id ) AS ts1 ON member_card.id = ts1.id
WHERE ( final_expire BETWEEN '2019-02-01' AND '2019-02-28' )
GROUP BY member_card.id
With my query, I would expect to find id 44, because his first transaction is made on 2018-02-01, so he will expire on the february 2019. But my query considers only LAST transaction (see MAX aggregate).
So, I need to search and looking for:
If exists a RENEW:
If yes, take this date and sum 365 (OR the custom expire date)
If no, take MIN transaction.
Thank you very much for your support.
Tryng to solve
I could also get the last renew transactions, with another query:
SELECT id_member_card , MAX(utc_date_t) AS last_transaction_renew
FROM transaction
WHERE description IS NOT NULL
GROUP BY id_member_card
and substitute these found id_member_card to the others, using this last_transaction_renew inside that IFNULL, but, how?
I have a table. It has a pk of id and an index of [service, check, datetime].
id service check datetime score
---|-------|-------|----------|-----
1 | 1 | 4 |4/03/2009 | 399
2 | 2 | 4 |4/03/2009 | 522
3 | 1 | 5 |4/03/2009 | 244
4 | 2 | 5 |4/03/2009 | 555
5 | 1 | 4 |4/04/2009 | 111
6 | 2 | 4 |4/04/2009 | 322
7 | 1 | 5 |4/05/2009 | 455
8 | 2 | 5 |4/05/2009 | 675
Given a service 2 I need to select the rows for each unique check where it has the max date. So my result would look like this table.
id service check datetime score
---|-------|-------|----------|-----
6 | 2 | 4 |4/04/2009 | 322
8 | 2 | 5 |4/05/2009 | 675
Is there a short query for this? The best I have is this, but it returns too many checks. I just need the unique checks at it's latest datetime.
SELECT * FROM table where service=?;
First you need find out the biggest date for each check
SELECT `check`, MAX(`datetime`)
FROM YourTable
WHERE `service` = 2
GROUP BY `check`
Then join back to get the rest of the data.
SELECT Y.*
FROM YourTable Y
JOIN ( SELECT `check`, MAX(`datetime`) as m_date
FROM YourTable
WHERE `service` = 2
GROUP BY check) as `filter`
ON Y.`service` = `filter`.service
AND Y.`datetime` = `fiter`.m_date
WHERE Y.`service` = 2
Following on from this question SELECT all the newest record distinct keyword with a non null value in one column
I now have a problem where I have this data
PRODUCT:
id| product | amount| ownershipid
1 | ipod | 200 | 2
2 | ipod | 250 | 3
3 | ipod | 150 | 4
4 | apple | 100 | 1
5 | apple | 98 | 2
6 | apple | 500 | 3
7 | itunes | NULL | 1
8 | itunes | 50 | 2
9 | itunes | NULL | 3
10 | itunes | NULL | 4
OWNERSHIP:
ownershipid| start | end
1 | 2011-01-01 | 2011-12-31
2 | 2012-01-01 | 2012-12-31
3 | 2014-01-01 | 2014-12-31
4 | 2013-01-01 | 2013-12-31
I need the most recent amount available for each product. I can not do an order by on ownershipId as the most recent data is from 2014. not from 2013. OwnershipId is Autoincrement and we accept historic data.
So, my result should return rows 2, 6 and 8.
Assuming most recent is defined by end, you can do a somewhat convoluted join to get the result;
SELECT p.product, p.amount
FROM product p JOIN ownership o ON p.ownershipid = o.ownershipid
JOIN (
SELECT p.product, MAX(o.end) end
FROM product p JOIN ownership o ON p.ownershipid = o.ownershipid
WHERE p.amount IS NOT NULL GROUP BY p.product) z
ON p.product = z.product AND o.end = z.end;
An SQLfiddle to test with.
The inner query gets the max date that has a non null amount per item.
The outer query gets the amount for that time/product.
I have a table with columns start_date and end_date. What we need to do is Select everything and group them by date conflicts for each Object_ID.
A date conflict is when a row's start date and/or end date pass through another rows'. For instance, here are some examples of conflicts:
Row 1 has dates 1st through the 5th, Row 2 has dates 2nd through the 3rd.
Row 1 has dates 2nd through the 5th, Row 2 has dates 1st through the 3rd.
Row 1 has dates 2nd through the 5th, Row 2 has dates 3rd through the 6th.
Row 1 has dates 2nd through the 5th, Row 2 has dates 1st through the 7th.
So for example, if we have some sample data (assume the numbers are just days of the month for simplicity):
id | object_id | start_date | end_date
1 | 1 | 1 | 5
2 | 1 | 2 | 4
3 | 1 | 6 | 8
4 | 2 | 2 | 3
What i would expect to see is this:
object_id | start_date | end_date | numconflicts
1 | <na> | <na> | 2
1 | 6 | 8 | 0 or null
2 | 2 | 3 | 0 or null
And for a Second Test Case, Here is some sample data:
id | object_id | start_date | end_date
1 | 1 | 1 | 5
2 | 1 | 2 | 4
3 | 1 | 6 | 8
4 | 2 | 2 | 3
5 | 2 | 4 | 5
6 | 1 | 2 | 3
7 | 1 | 10 | 12
8 | 1 | 11 | 13
And for the second Test Case, what I would expect to see as output:
object_id | start_date | end_date | numconflicts
1 | <na> | <na> | 3
1 | 6 | 8 | 0 or null
2 | 2 | 3 | 0 or null
2 | 4 | 5 | 0 or null
1 | <na> | <na> | 2
Yes, I will need some way of differentiating the first and the second grouping (the first and last rows) but I haven't quite figured that out. The goal is to view this list, and then when you click on a group of conflicts you can view all of the conflicts in that group.
My first thought was to attempt some GROUP BY CASE ... clause but I just wrapped by head around itself.
The language I am using to call mysql is php. So if someone knows of a php-loop solution rather than a large mysql query i am all ears.
Thanks in advance.
Edit: Added in primary Keys to provide a little less confusion.
Edit: Added in a Test case 2 to provide some more reasoning.
This query finds the number of duplicates:
select od1.object_id, od1.start_date, od1.end_date, sum(od2.id is not null) as dups
from object_date od1
left join object_date od2
on od2.object_id = od1.object_id
and od2.end_date >= od1.start_date
and od2.start_date <= od1.end_date
and od2.id != od1.id
group by 1,2,3;
You can use this query as the basis of a query that gives you exactly what you asked for (see below for output).
select
object_id,
case dups when 0 then start_date else '<na>' end as start_date,
case dups when 0 then end_date else '<na>' end as end_date,
sum(dups) as dups
from (
select od1.object_id, od1.start_date, od1.end_date, sum(od2.id is not null) as dups
from object_date od1
left join object_date od2
on od2.object_id = od1.object_id
and od2.end_date >= od1.start_date
and od2.start_date <= od1.end_date
and od2.id != od1.id
group by 1,2,3) x
group by 1,2,3;
Note that I have used an id column to distinguish the rows. However, you could replace the test of id's not matching with comparisons on every column, ie replace od2.id != od1.id with tests that every other column is not equal, but that would require a unique index on all the other columns to make sense, and having an id column is a good idea anyway.
Here's a test using your data:
create table object_date (
id int primary key auto_increment,
object_id int,
start_date int,
end_date int
);
insert into object_date (object_id, start_date, end_date)
values (1,1,5),(1,2,4),(1,6,8),(2,2,3);
Output of first query when run against this sample data:
+-----------+------------+----------+------+
| object_id | start_date | end_date | dups |
+-----------+------------+----------+------+
| 1 | 1 | 5 | 1 |
| 1 | 2 | 4 | 1 |
| 1 | 6 | 8 | 0 |
| 2 | 2 | 3 | 0 |
+-----------+------------+----------+------+
Output of second query when run against this sample data:
+-----------+------------+----------+------+
| object_id | start_date | end_date | dups |
+-----------+------------+----------+------+
| 1 | 6 | 8 | 0 |
| 1 | <na> | <na> | 2 |
| 2 | 2 | 3 | 0 |
+-----------+------------+----------+------+
Oracle : This could be done with a subquery in a group by CASE statement.
https://forums.oracle.com/forums/thread.jspa?threadID=2131172
Mysql : You could have a view which had all the conflicts .
select distinct a1.appt, a2.appt from appointment a1, appointment a2 where a1.start < a2.end and a1.end > a2.start.
and then simply do a count(*) on that table.
Something like the following should work:
select T1.object_id, T1.start_date, T1.end_date, count(T1.object_id) as numconflicts
from T1
inner join T2 on T1.start_date between T2.start_date and T2.end_date
inner join T3 on T1.end_date between T2.start_date and T2.end_date
group by T1.object_id
I might be off a little bit, but it should help you get started.
Edit: Indented it properly