Group rows without "GROUP BY" expression in mysql - mysql

I have this table and I would like to do the following :
idstep idproject beg_date end_date
1 1
2 1
3 1
4 1
1 2
2 2
3 2
4 2
5 2
1 3
2 3
3 3
Retrieve the Maximum steps for each project without using "GROUP BY"
Using the GROUP BY clause, I get the result that I want which is the following:
SELECT MAX(idstep), idproject
FROM mytable
GROUP BY idproject;
Result:
idstep idproject
4 1
5 2
3 3
Please, can anyone here can help me out with this issue?

I agree that this makes more sense to use GROUP BY for this particular case, but this should work:
SELECT t.project, t.step
FROM YourTable t
LEFT JOIN YourTable t2 on t.step < t2.step and t.project = t2.project
where t2.step IS NULL
And here is the Fiddle.
You could also use NOT EXISTS (feel like I've been using it all night), although I personally prefer the LEFT JOIN / NULL approach:
SELECT t.project, t.step
FROM YourTable t
WHERE NOT EXISTS (
SELECT *
FROM YourTable t2
WHERE t.step < t2.step
AND t.project = t2.project
)
More fiddle: http://www.sqlfiddle.com/#!2/ebbc2/1
Good luck.

Related

How can I get the result from mysql after group and order

I have the following tables
t1
id
stage
1
1,2,3
2
2,3,4
t2
id
t_id
stage_id
1
1
2
2
1
1
3
1
3
4
2
2
5
2
4
6
2
3
I hope the result can first order by t2.t_id and then order by the value of t1.stage
like the following result
t_id
stage_id
1
1
1
2
1
3
2
2
2
3
2
4
I have the following sql ,but it do not work.So what should I do?
SELECT
t2.t_id,
t2.stage_id
FROM
t2
LEFT JOIN t1 ON t1.id = t2.t_id
GROUP BY
t2.t_id,
t2.stage_id
ORDER BY
t2.t_id,
field(t2.stage_id, t1.stage)
FIELD() requires each value to sort by to be a separate argument.
FIND_IN_SET() returns the index in a comma-separated string.
SELECT
t2.t_id,
t2.stage_id
FROM
t2
LEFT JOIN t1 ON t1.id = t2.t_id
GROUP BY
t2.t_id,
t2.stage_id
ORDER BY
t2.t_id,
find_in_set(t2.stage_id, t1.stage)
Note that this only corrects the ordering criteria in your SQL. This won't necessarily return the first row in each group by that ordering (and will get an error if the ONLY_FULL_GROUP_BY SQL mode is enabled). See SQL Selecting from two Tables with inner join and limit for the correct way to do that.

MySQL:Case Statement Issue

Complaint_status Table : multiple rows for a complaints
id complaint_id status_type status_value
1 11 2 0
2 11 2 2
3 11 2 1
4 11 2 2
Trying to get min(id) having status_type=2 and status_value=2 but showing null,have to use case statement for doing other stuff.
SELECT c3.id AS Ticket_id,
CASE
WHEN cs.status_value=2 THEN cs.created_at
ELSE NULL
END AS Closure_date
FROM complaint c3
INNER JOIN complaint_status cs ON cs.complaint_id=c3.id
WHERE cs.id IN
(SELECT min(id)
FROM complaint3_status
WHERE complaint_id=c3.id
AND status_type=2)
AND c3.id IN(11)
Here is one method that gives you the entire row:
select cs.*
from complaint_status cs
where status_type = 2 and status_value = 2
order by id asc
limit 1;
You can just use select id if that is all you want. I have no idea what case has to do with this query.

most frequent observation or median of a set

I am aggregating data and I cannot sum certain columns so I would like to take the most frequent observation from that column, or the median value. Example follows, thanks in advance.
ID site
1 3
1 3
1 2
1 3
2 4
2 5
2 5
2 5
I want it to look like
ID Site
1 3
2 5
WITH temp AS(
SELECT ID, Site, COUNT(*) As counts
FROM id_table
GROUP BY ID, Site
)
SELECT temp.ID, temp.Site
FROM temp
JOIN (SELECT ID, MAX(counts) max_counts
FROM temp
GROUP BY ID
)b
ON temp.ID = b.ID
AND temp.counts = b.max_counts
ORDER BY ID ASC
SQL Fiddle

Group dates based on variable periods

i have two tables as follows------
table-1
CalenderType periodNumber periodstartdate
1 1 01-01-2013
1 2 11-01-2013
1 3 15-01-2013
1 4 25-01-2013
2 1 01-01-2013
2 2 15-01-2013
2 3 20-01-2013
2 4 25-01-2013
table2
Incidents Date
xyz 02-01-2013
xxyyzz 03-01-2013
ccvvb 12-01-2013
vvfg 16-01-2013
x3 17-01-2013
x5 24-01-2013
Now i want to find out the number of incidents took place in a given period(the Calendar type may change on runtime like)
the query should look something like this
select .......
from ......
where CalendarType=1
which should return
CalendarType PeriodNumber Incidents
1 1 2
1 2 1
1 3 3
1 4 0
can someone suggest me an approach or any method how this can be achieved.
Note:each period is variable in size.peroid1 may have 10 days period2 may have 5 days etc.
I think this does what you want, although I don't understand how you arrived at your sample output:
select t.CalenderType, t.periodNumber, count(*) as Incidents
from Table1 t
inner join (
select t2.Date, t2.Incidents, max(t1.periodstartdate) as PeriodStartDate
from Table2 t2
inner join Table1 t1 on t2.Date >= t1.periodstartdate
where CalenderType = 1
group by t2.Date, t2.Incidents
) a on t.periodstartdate = a.PeriodStartDate
where CalenderType=1
group by t.CalenderType, t.periodNumber
SQL Fiddle Example
Try this, a bit more general solution,SQLFiddle (Thanks RedFilter for schema):
SELECT t1.CalenderType, t1.periodNumber, count(Incidents)
FROM Table1 t1, Table1 t11, Table2
WHERE
(
(
t1.CalenderType = t11.CalenderType
AND t1.periodNumber = t11.periodNumber - 1
AND Date BETWEEN t1.periodstartdate AND t11.periodstartdate
)
OR
(
t1.periodNumber = (SELECT MAX(periodNumber) FROM Table1 WHERE t1.CalenderType = CalenderType)
AND Date > t1.periodstartdate
)
)
GROUP BY t1.CalenderType, t1.periodNumber
ORDER BY t1.CalenderType, t1.periodNumber

first item used by a user

I am writing a query to grab the items that a specific user_id was the first to use. Here is some sample data -
item_id used_user_id date_used
1 1 2012-08-25
1 2 2012-08-26
1 3 2012-08-27
2 2 2012-08-27
3 1 2012-08-27
4 1 2012-08-21
4 3 2012-08-24
5 3 2012-08-23
query
select item_id as inner_item_id, ( select used_user_id
from test
where test.item_id = inner_item_id
order by date_used asc
limit 1 ) as first_to_use_it
from test
where used_user_id = 1
group by item_id
It returns the correct values
inner_item_id first_to_use_it
1 1
3 1
4 1
but the query is VERY slow on a giant table. Is there a certain index that I can use or a better query that I can write?
i can't get exactly what you mean because in your inner query you have sorted it by their used_user_id and and on your outer query you have filtered it also by their userid. Why not do this directly?
SELECT DISTINCT item_id AS inner_item_id,
used_user_id AS first_to_use_it
FROM test
WHERE used_user_id = 1
UPDATE 1
SELECT b.item_id,
b.used_user_id AS first_to_use_it
FROM
(
SELECT item_ID, MIN(date_used) minDate
FROM tableName
GROUP BY item_ID
) a
INNER JOIN tableName b
ON a.item_ID = b.item_ID AND
a.minDate = b.date_used
WHERE b.used_user_id = 1