Column calculated by column with grouping - mysql

I have a simple table -
id | date | type | value
-------------------------
1 1/1/14 A 1
2 1/1/14 A 10
3 2/1/14 A 10
4 2/1/14 A 15
5 2/1/14 B 15
6 2/1/14 B 20
I would like to create a new column which calculates the minimum value per day per type. So giving the following results -
id | date | type | value | min_day
-----------------------------------
1 1/1/14 A 1 1
2 1/1/14 A 10 1
3 2/1/14 A 10 10
4 2/1/14 A 15 10
5 2/1/14 B 15 15
6 2/1/14 B 20 15
Is this possible? If so how would I go about it? I've been looking into triggers.
Thanks for any help.

First create a field named min_day in your table. Then you can use JOIN in an UPDATE query.
Try this:
UPDATE TableName T1 JOIN
(SELECT date,type,MIN(value) as MinValue
FROM TableName
GROUP BY type,date) T2 ON T1.type=T2.type AND T1.date=T2.date
SET T1.min_day = T2.MinValue
An example in SQL Fiddle.
EDIT:
For day-wise grouping:
UPDATE TableName T1 JOIN
(SELECT MONTH(date) as mon,type,MIN(value) as MinValue
FROM TableName
GROUP BY type,MONTH(date)) T2 ON T1.type=T2.type AND MONTH(T1.date)=T2.mon
SET T1.min_day = T2.MinValue
Result in SQL Fiddle.

Assuming that your table's name is mytable, try this:
SELECT mt.id,
mt.date,
mt.type,
mt.value,
mt.min_day,
md.min_value
FROM mytable mt
LEFT JOIN
(SELECT date, MIN(value) min_value FROM mytable GROUP BY DATE
) md
ON mt.date=md.date;

SELECT t1.*,
t2.min_day
FROM Table1 AS t1
JOIN
(SELECT date,TYPE,
min(value) AS min_day
FROM table1
GROUP BY date,TYPE) AS t2 ON t1.TYPE = t2.TYPE
AND t1.date = t2.date

Related

How to select All the rows from first table and get count of all the matching rows from other table for each row retrived from first table

Following are the tables
Table 1
price col1 col2 time
10 1 1 10
100 1 1 13
150 1 1 15
Table 2
id startTm endTm col1 col2
1 12 20 1 1
2 15 26 1 1
3 11 13 1 1
I want all the rows from table 2 satisfying startTm >= x and endTm <= y. And for each row in result I want to find count of all the records in table 1 where table1.time lies in startTm and endTm for that particular row
Something like this-
SELECT (#sTime:=T2.startTm) AS startTm,JT.totalNo, JT.totalPrice,
(#eTime:=T2.endTm) AS endTm
some more columns FROM table 2 AS T2
LEFT JOIN (SELECT COUNT(id) AS totalNo,col1, col2 SUM(price) AS
totalPrice FROM table 1 WHERE time BETWEEN #sTime AND #eTime GROUP
BY col1, col2)
AS JT ON JT.col1 = T2.col1
WHERE T2.startTm >= some value AND T2.endTm <= some value.
There are no related foreign keys.I Am not getting proper results. How is it done?
Edit
I want all the records from table 2 within specified time range suppose startTm >= 10 to endTm<=20
so output table will be
startTm endTm totalNo totalPrice some more col
12 20 2 250 ...
11 13 1 100 ...
to calculate total Price and total number I want to consider startTm and endTime of that particular row.
Is this what you want?
SELECT startTm, endTm, COUNT(price), SUM(price), t3_others, t1_others
FROM
(
SELECT T3.startTm AS startTm, T3.endTm AS endTm, T3.others AS t3_others, T1.price AS price, T1.others AS t1_others
FROM T1
RIGHT JOIN
(
SELECT T2.startTm, T2.endTm, T2.others
FROM T2
WHERE T2.startTm >= 10 AND T2.endTm <= 20 AND T2.col1 = col1_value AND T2.col2 = col2_value
) AS T3
ON T1.time >= T3.startTm AND T1.time <= T3.endTm
) AS T4
GROUP BY startTm, endTm;
Add other more fields as you need.
Try Following Query:
Select t1.* , t2.* from Table 1 as t1 RIGHT JOIN Table 2 as t2 ON t1.col1 = t2.col1 WHERE t2.startTm >= 'your value' AND t2.endTm <= 'your value'

select id from table with max date and max id if dates are the same

For an example I have MySQL table like:
id category date value
1 a 2013-01-02 7
2 a 2013-01-01 2
3 a 2013-01-01 3
4 b 2013-01-01 1
5 b 2013-01-02 4
6 b 2013-01-03 5
7 c 2013-01-03 4
8 c 2013-01-03 8
I need select records with MAX(date) for each category, but if date is the same, with MAX(id).
So, expected result must be:
id category date value
1 a 2013-01-02 7
6 b 2013-01-03 5
8 c 2013-01-03 8
As you can see, dates for same category can be not sorted (like id=4,5).
I tried query like:
SELECT * FROM mytable t1
INNER JOIN
(
SELECT category, MAX(date) AS MAXDATE
FROM mytable
GROUP BY category
) t2
ON t1.category = t2.category
AND t1.date = t2.MAXDATE
It works fine, when we have no same dates in table. But for my case, it will return records with lowest ids:
id category date value
1 a 2013-01-01 7
6 b 2013-01-03 5
7 c 2013-01-03 4
You are on the right track but you need to change your join.
I think what you want is the following:
SELECT * FROM mytable t1
INNER JOIN
(
SELECT MAX(id) AS ID, MAX(date) AS MAXDATE
FROM mytable
GROUP BY category
) t2
ON t1.id = t2.ID
AND t1.date = t2.MAXDATE
As mentioned, the previous wont work for every use case. The following might.
SELECT a.*
FROM mytable AS a,
(
SELECT category, date, MAX(id) AS ID
FROM mytable
GROUP BY category, date
) AS b,
(
SELECT category, MAX(date) AS date
FROM mytable
GROUP BY category
) AS c
WHERE b.category = c.category
AND b.date = c.date
AND a.id = b.id

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

how is this query done in mysql?

Given the following table ...
ID USER NUM
1 1 69
2 2 75
3 3 7
4 1 31
5 2 18
6 3 70
7 1 12
8 2 23
9 3 42
... which query would return rows with the lowest NUM for each USER?
The result should look like ...
ID USER NUM
7 1 12
5 2 18
3 3 7
Can't wrap my head around this one! Assuming it has a GROUP BY, but everything I try fails... Any pointers?
SELECT t.*
FROM tablename t
INNER JOIN (SELECT user, MIN(num) num
FROM tablename
GROUP BY user) x ON t.user = x.user AND t.num = x.num
or
SELECT t1.*
FROM tablename t1
LEFT JOIN tablename t2 ON t1.user = t2.user AND t1.num > t2.num
WHERE t2.id IS NULL
SELECT ID , MIN(NUM) as MIN_NUM , USER FROM usertable GROUP BY USER
Have a look at demo http://sqlfiddle.com/#!2/ce2fd/1
HEre is another method. UPDATED WITH THE CORRECT REREFERENCE
SQLFIDDLE
Query
select b.id, a.user, a.minnum from
mytable as b
join
(select user, min(num) as minnum
from mytable
group by user
) as a
on b.user = a.user
where b.num = a.minnum
order by a.minnum asc
limit 3
;
Results:
ID USER MINNUM
3 3 7
7 1 12
5 2 18

Select distinct values from two columns

I have a table with the following structure:
itemId | direction | uid | created
133 0 17 1268497139
432 1 140 1268497423
133 0 17 1268498130
133 1 17 1268501451
I need to select distinct values for two columns - itemId and direction, so the output would be like this:
itemId | direction | uid | created
432 1 140 1268497423
133 0 17 1268498130
133 1 17 1268501451
In the original table we have two rows with the itemId - 133 and direction - 0, but we need only one of this rows with the latest created time.
Thank you for any suggestions!
Use:
SELECT t.itemid,
t.direction,
t.uid,
t.created
FROM TABLE t
JOIN (SELECT a.itemid,
MAX(a.created) AS max_created
FROM TABLE a
GROUP BY a.itemid) b ON b.itemid = t.itemid
AND b.max_created = t.created
You have to use an aggregate (IE: MAX) to get the largest created value per itemid, and join that onto an unaltered copy of the table to get the values associated with the maximum created value for each itemid.
select t1.itemid, t1.direction, t1.uid, t1.created
from (select t2.itemid, t2.direction, t2.created as maxdate
from tbl t2
group by itemid, direction) x
inner join tbl t1
on t1.itemid = x.itemid
and t1.direction = x.direction
and t1.created = x.maxdate