mySQL ORDER based on multiple criteria - mysql

My actual table is much more in-depth than this but let's assume I have a table that looks like this...
Record_ID Due_Date Style
========= ========== =====
100 2018-01-01 10
101 2018-01-02 20
102 2018-01-03 12
103 2018-01-04 10
104 2018-01-05 20
105 2018-01-06 12
106 2018-01-02 10
What I want is a query that will determine the first due date and then return that record along with all other records with the same style regardless of the due date. It should then be followed by the next due date of another style and keep going. A successful output would be in this order...
Record_ID Due_Date Style
========= ========== =====
100 2018-01-01 10
106 2018-01-02 10
103 2018-01-04 10
101 2018-01-02 20
104 2018-01-05 20
102 2018-01-03 12
105 2018-01-06 12
If you look at just the first record for each Style the output is in order.
See records 100,101,102
If you look at all the records for a given Style the output is sorted by date.
See records 100,106,103
If you look at just the Style column the output is has all the like Style together but not necessarily in numerical order.
By doing having this output, it is easy to see what Style is due first but all records in that same Style will be completed prior to moving on to the next Style

Here's one option using a subquery that creates a grouping of styles with their corresponding min(duedate). Then you join that back to the original table and order by that date.
select *
from yourtable t join (
select min(duedate) minduedate, style
from yourtable
group by style) t2 on t.style = t2.style
order by t2.minduedate, t.duedate
Online Demo

Related

Normalizing overlapping date ranges while extending if its overlapping

I have a table of date ranges that often overlap.
I want to
adjust the date range if it overlaps with an earlier date range
normalize
Get sum of overlaps
Get # of records merged
Example
Start Date
End Date
2018-01-02
2018-01-04
2018-01-05
2018-01-07
2018-01-07
2018-01-10
2018-01-12
2018-01-15
Step 1 . Adjust date range if it overlaps with an earlier date range
Start Date
End Date
2018-01-02
2018-01-04
2018-01-05
2018-01-07
2018-01-08
2018-01-11
2018-01-12
2018-01-15
Step2: Normalize, Get sum of overlaps, and count of records merged
Start Date
End Date
Overlap
Ct
2018-01-02
2018-01-15
1
4
I'm using Teradata.
I've previously used NORMALIZE ON MEETS AND OVERLAPS to normalize but I don't know how to get the amount of overlap and the count of records that were merged.
I've though of using NPATH but I can't figure out how to calculate amount of overlap.
(Teradata NORMALIZE options)

Is there a way to include double condition in HAVING?

I'm currently working on a query that looks like this. There are two tables - members and member_gathering.
SELECT id, city_id, name FROM members
WHERE "id" = "member_id" IN
(
SELECT "member_id" from member_gathering
GROUP BY "member_id"
HAVING COUNT(DATEDIFF("visited","joined">=365))>=5
ORDER BY "member_id"
)
ORDER BY id*1;
The goal is to have an output of all IDs satisfying the condition of being in more than 5 groups, in which a member is active for more than a year. Being active means having a difference between "visited" and "joined" columns (both are TIMESTAMP) for more than a year (I set that as 365 days).
However, after running, this code shows all the rows in a members table (though manual check of both tables shows that some rows do not satisfy both conditions at the same time).
Any ideas on how to improve the code above? I'm not sure if I can use 'nested' condition inside COUNT(), but all other variants used before show either NULL values or returned all rows in the table, which is obviously not right. Also, I was thinking that problem might be with DATEDIFF function.
All suggestions are welcome: I'm a newbie to MySQL, so I'm not that familiar with it.
UPD: data sample:
1) members
id city_id name
2 980 Joey
5 980 Carl
10 1009 Louis
130 1092 Andrea
2) member_gathering
member_id gathering_id joined visited
2 1 2010-01-01 00:00:00 2010-02-01 00:00:00
2 2 2010-01-01 00:00:00 2010-02-01 00:00:00
5 2 2010-01-01 00:00:00 2010-02-01 00:00:00
10 3 2010-01-01 00:00:00 2010-02-01 00:00:00
130 1 2010-02-01 00:00:00 2013-02-01 00:00:00
130 2 2010-02-01 00:00:00 2013-02-01 00:00:00
130 3 2010-02-01 00:00:00 2014-02-01 00:00:00
130 4 2010-02-01 00:00:00 2018-02-01 00:00:00
130 5 2010-02-01 00:00:00 2015-02-01 00:00:00
Expected result would be only ID 130, thus: 130, 1092, Andreana.
I believe you first need to find all records where datediff is 365 days or more. Then find members who have 5 or more such instances. This needs both WHERE and HAVING clause:
SELECT id, city_id, name
FROM members
WHERE id IN (
SELECT member_id
FROM member_gathering
WHERE DATEDIFF(visited, joined) >= 365
GROUP BY member_id
HAVING COUNT(*) >= 5
)
You could use this way
SELECT id, city_id, name FROM members
WHERE member_id IN
(
SELECT member_id from member_gathering
GROUP BY member_id
HAVING SUM(DATEDIFF(visited, joined) >= 365)>=5
ORDER BY member_id
)
You should use separated expression for count differente category of datediff and remmeber that count work for not null values so if you want obtain the totale for true values you should sue SUM

MYSQL - how to get all records from specific record

I have been trying hard to find how to get all records from specific record in a sql query. I am able to do it in a different way but looks unprofessional.
For example, I have following table
-----------------------
id name sessionid
-----------------------
1 dav 88
2 dav 88
3 dav 99
4 po 100
5 nav 111
6 dav 99
7 nav 120
I would like to fetch all records from id 3 to id 7 and the result should look like this
-----------------------
id name sessionid
-----------------------
3 dav 99
4 po 100
5 nav 111
6 dav 99
7 nav 120
Thanks for your help.
Based on your last comment, I'll give it a try:
select *
from x
where id >= (
select min(id)
from x
where sessionid = 99
)
Is that what you mean?
Isn't it just this?
SELECT * FROM table where table.id BETWEEN 3 AND 7

Select rows from last existing 12 months

There's a DATETIME column called time. How could I select all rows that fall within the last existing 12 months (NOT within the last year from today)? Not every month might have a row, and months may have more than one row.
For example, out of this table (ORDER BY time DESC), rows with ids 2 to 17 would be selected.
id time
-- ----
17 2015-04-01
16 2015-04-01
15 2015-03-01
14 2015-02-01
13 2015-01-01
12 2014-12-01
11 2014-11-01
10 2014-10-01
9 2013-12-01
8 2013-11-01
7 2013-10-01
6 2013-09-01
5 2013-09-01
4 2013-09-01
3 2013-09-01
2 2013-08-01
1 2013-07-01
Another way to put this:
Take the table above and group by month/year, so we get:
2015-04
2015-03
2015-02
2015-01
2014-12
2014-11
2014-10
2013-12
2013-11
2013-10
2013-09
2013-08
2013-07
Now take the 12 most recent months from this list, which is everything except 2013-07.
2015-04
2015-03
2015-02
2015-01
2014-12
2014-11
2014-10
2013-12
2013-11
2013-10
2013-09
2013-08
And select everything from those months.
I guess I could do this with multiple queries or subqueries but is there another way to do this?
If your time field is only month-precision, you could do it with a pretty simple subselect:
SELECT * FROM Table t1
WHERE time IN (
SELECT DISTINCT time FROM Table t2 ORDER BY time DESC LIMIT 12
)
If your timestamps are full-precision, you could do the same thing, but you'd need to do some date manipulation to round the dates to the month for comparison.

Select Distinct Column For Each Value In Another Column Then Group By

I am pretty new to mySQL and I have had a hard time over the past 2 days trying to get this to work. I do not know if the title is correct in relation on what I am trying to fix, but if it is not, please correct me.
Here is the deal:
I have 4 columns... id, number, package_id, and date.
id - Increments every time a new row is inserted
number - Just a 2 digit number
package_id - ID of package
date - date and time row was inserted
Here is what an example table looks like: (I omitted the time from the date)
id number package_id date
--- ------ ---------- ----
1 12 20 08-01-2013
2 12 21 08-01-2013
3 12 20 08-01-2013
4 45 20 08-02-2013
5 45 22 08-02-2013
6 45 22 08-03-2013
7 12 20 08-03-2013
8 70 25 08-03-2013
9 70 26 08-03-2013
10 70 25 08-03-2013
Not only am I trying to select distinct for number and group by date. I am also trying to make sure it does it for each unique value in the package_id column.
To better explain, this is what i want the output to be like when I SELECT *:
id number package_id date
--- ------ ---------- ----
1 12 20 08-01-2013
2 12 21 08-01-2013
4 45 20 08-02-2013
5 45 22 08-02-2013
6 45 22 08-03-2013
7 12 20 08-03-2013
8 70 25 08-03-2013
9 70 26 08-03-2013
As you can see only row 3 and 10 did not get selected because of the same number and package_id together within the same day.
How can I accomplish this?
Is this what you are looking for:
SELECT MIN(id), number, package_id, date
FROM MyTable
GROUP by number, package_id, date
It certainly satisfies your expected result set.