I'm new to SQL, but I'm pretty sure something strange is happening here. I have a MySQL database with a table (eventtable) with 4 columns (RoomNum, EventName, EventStatus, EventDateTime).
Certain EventNames repeat with the EventStatus toggling ON and OFF at different times. I'm trying to get the latest entry so that I have the "current" state, so I use:
select RoomNum, EventName, EventStatus, max(EventDateTime) as MaxDate
from eventtable where eventName = "DND"
group by RoomNum
Resulting in:
Just to make sure everything is ok, I check each room to make sure it is giving the latest one with:
SELECT * FROM `eventtable`
where RoomNum = "070#" and eventname = "DND" /*where "#" is a specific digit*/
order by eventdatetime asc
The first one looked good:
But then the others don't! (The EventStatus is wrong even though the time is correct):
what I don't get is that EventDateTime matches which tells me I'm looking at the same row of data, but then how can the internal value (EventStatus) be different?
Please help. Thank you.
By using below query, You can get the result as per your requirement. Please try.
select * from(select RoomNum, EventName, EventStatus, EventDateTime from eventtable where eventName = "DND" order by EventDateTime desc)tab group by RoomNum ;
This is why firebird does not allow this. Only this is valid
select RoomNum, max(EventDateTime) as MaxDate
from eventtable where eventName = "DND"
group by RoomNum
EventName and EventStatus values are arbitrary. You have not told it which ones you want. And I don't think you can. RoomNumn is implicit because of "group by".
To get the data you want, one way would be to use a subselect where the max(EventDateTime) returns a reference.
Related
My problem is the following, I want set a list of ID in a variable, then use this variable in a subquery. The problem is that WorkBench (my GUI) return the following error : "subquery returning multiple rows". It seems to me that's what I want.
Please explain me where I am wrong.
This is my query :
set #listID := (select ID_VOIE as ID from voies
where ORIGINE = 'XXX'
group by CODE_INSEE, CODE_VOIE
having count(*) > 1);
select substring(v.CODE_INSEE,1,2), count(*) from voies v
where v.ID_VOIE in (#listID)
group by substring(vs.CODE_INSEE,1,2);
The thing is I'm blocked with the "group by", I want do a groupd by after a first group by, that's why I can't (or at least i didn't find a way) write the request with a single WHERE clause.
The thing is I know that I can put the whole request directly in my subquery instead of using variable but :
It can let me use this trick in another requests that needed this behaviour (DRY concept !)
I'm not sure but the subquery will be executed in each turn of my loop, and that will be very inefficient
So I seek 2 possible ways : a way that let me use a list in a variable in a subquery OR a way that let me use "group by" twice in a single query.
Thanks you in advance for your answers (oh and sorry for my english, this is not my maternal language).
Unless you need that variable for something else, you should be able to skip it entirely as follows:
SELECT
SUBSTRING(v.CODE_INSEE,1,2),
COUNT(*)
FROM
voies v
WHERE
v.ID_VOIE in
(SELECT
ID_VOIE as ID
FROM
voies
WHERE
ORIGINE = 'XXX'
GROUP BY
CODE_INSEE,
CODE_VOIE
HAVING COUNT(*) > 1)
GROUP BY
SUBSTRING(vs.CODE_INSEE,1,2);
As you say, the subquery will be executed for all rows. To avoid that, a variable would be best, but MySQL doesn't support table variables. Instead, you can use a temporary table:
IF EXISTS DROP TABLE myTempTable;
CREATE TEMPORARY TABLE myTempTable (ID_VOIE int); -- I don't know the datatype
INSERT INTO myTempTable (ID_VOIE)
SELECT DISTINCT -- using distinct so I can join instead of use IN.
ID_VOIE as ID from voies
WHERE
ORIGINE = 'XXX'
GROUP BY
CODE_INSEE, CODE_VOIE
HAVING COUNT(*) > 1
And now you can do this:
SELECT
SUBSTRING(v.CODE_INSEE,1,2), COUNT(*)
FROM
voies v
JOIN myTempTable tt ON
v.ID_VOIE = tt.ID_VOIE
GROUP BY SUBSTRING(vs.CODE_INSEE,1,2);
I'm stucked in a MySQL problem that I was not able to find a solution yet. I have the following query that brings to me the month-year and the number new users of each period in my platform:
select
u.period ,
u.count_new as new_users
from
(select DATE_FORMAT(u.registration_date,'%Y-%m') as period, count(distinct u.id) as count_new from users u group by DATE_FORMAT(u.registration_date,'%Y-%m')) u
order by period desc;
The result is the table:
period,new_users
2016-10,103699
2016-09,149001
2016-08,169841
2016-07,150672
2016-06,148920
2016-05,160206
2016-04,147715
2016-03,173394
2016-02,157743
2016-01,173013
So, I need to calculate for each month-year the difference between the period and the last month-year. I need a result table like this:
period,new_users
2016-10,calculate(103699 - 149001)
2016-09,calculate(149001- 169841)
2016-08,calculate(169841- 150672)
2016-07,So on...
2016-06,...
2016-05,...
2016-04,...
2016-03,...
2016-02,...
2016-01,...
Any ideas: =/
Thankss
You should be able to use a similar approach as I posted in another S/O question. You are on a good track to start. You have your inner query get the counts and have it ordered in the final direction you need. By using inline mysql variables, you can have a holding column of the previous record's value, then use that as computation base for the next result, then set the variable to the new balance to be used for each subsequent cycle.
The JOIN to the SqlVars alias does not have any "ON" condition as the SqlVars would only return a single row anyhow and would not result in any Cartesian product.
select
u.period,
if( #prevCount = -1, 0, u.count_new - #prevCount ) as new_users,
#prevCount := new_users as HoldColumnForNextCycle
from
( select
DATE_FORMAT(u.registration_date,'%Y-%m') as period,
count(distinct u.id) as count_new
from
users u
group by
DATE_FORMAT(u.registration_date,'%Y-%m') ) u
JOIN ( select #prevCount := -1 ) as SqlVars
order by
u.period desc;
You may have to play with it a little as there is no "starting" point in counts, so the first entry in either sorted direction may look strange. I am starting the "#prevCount" variable as -1. So the first record processed gets a new user count of 0 into the "new_users" column. THEN, whatever was the distinct new user count was for the record, I then assign back to the #prevCount as the basis for all subsequent records being processed. yes, it is an extra column in the result set that can be ignored, but is needed. Again, it is just a per-line place-holder and you can see in the result query how it gets its value as each line progresses...
I would create a temp table with two columns and then fill it using a cursor that
does something like this (don't remember the exact syntax - so this is just a pseudo-code):
#val = CURSOR.col2 - (select col2 from OriginalTable t2 where (t2.Period = (CURSOR.Period-1) )))
INSERT tmpTable (Period, NewUsers) Values ( CURSOR.Period, #val)
I have a table like this:
ID Severity WorkItemSK
23636 3-Minor 695119
23636 3-Minor 697309
23647 2-Major 695081
23647 2-Major 694967
In here I have several WorkItems that share the same ID. How can I get unique IDs that have the highest WorkItem?
So it would like this:
ID Severity WorkItemSK
23636 3-Minor 697309
23647 2-Major 695081
Help the noob :) Mind giving a clue what SQL commands (again I am a noob) should I use? Or an example of a query?
Thank you in advance!
Assuming that Severity can change depending on the WorkItemSK, you'll want to use the following query:
Select T.ID, T.Severity, T.WorkItemSK
From Table T
Join
(
Select ID, Max(WorkItemSK) As WorkItemSK
From Table
Group By ID
) D On T.WorkItemSK = D.WorkItemSK And T.ID = D.ID
The last Join condition of T.ID = D.ID may or may not be needed, depending on whether WorkItemSK can appear multiple times in your table.
Otherwise, you can just use this:
Select ID, Severity, Max(WorkItemSK) As WorkItemSK
From Table
Group by ID, Severity
But if you have different Severity values per ID, you'll see duplicate IDs.
Use select with GROUP BY: SELECT id,MAX(WorkItemSK) FROM table GROUP BY id;
I got specific query:
SELECT *
FROM stats
WHERE mod_name = 'module'
GROUP BY domain
ORDER BY addition_date DESC
I want to retrive, the newest value for every domain. I know there is a domain x.com value with date 2014-02-19.
However, this query returns me row with date: 2014-01-06
That's quite simple query... why it does not take group by domains and take only newest value?
Am I missing something?
The order by takes place after the group by. That is why your query does not work. Here is a way to get what you want:
SELECT s.*
FROM stats s
WHERE mod_name = 'module' and
not exists (select 1
from stats s2
where s2.mod_name = s.mod_name and
s2.addition_date > s.addition_date
)
ORDER BY addition_date DESC;
To get the best performance, create an index on stats(mod_name, addition_date).
My query is:
SELECT temp.pid FROM
(SELECT postid, date FROM swapping AS s, post AS p
WHERE s.mid='2' AND p.postid=s.postid) AS temp
WHERE temp.date = (SELECT MAX(date) FROM temp)
I receive #1146 - Table 'databasename.temp' doesn't exist
How can I make it work?
Thank you.
It seems like you want to select the last "pid", in terms of "date", where s.mid='2'
Try this (after you figure out where pid comes from and correct the first line)
SELECT [s? or maybe p?].pid
FROM swapping s INNER JOIN post p ON p.postid=s.postid
WHERE s.mid = '2'
ORDER BY date DESC
LIMIT(0,1)
You might also need to alias the date column in the order by line.
I think you have your column incorrect...
SELECT temp.pid FROM ( SELECT postid, ...
should be
SELECT temp.postid FROM ( SELECT postid, ...
#DRapp hit the nail on the head at least. You haven't selected 'pid' (if that column exists in either the swapping or post table) in your sub selection that your referring to as temp so it would throw some type of error there.