get latest(date) row of groups - mysql

my problem is, that I stuck with this I guess simple problem.
Now 2 evenings Grrr...
I created a small example to keep it simple:
The source table looks like that: Some obj with some random status.
These statuses can be changed/updated by insert a new row.
Id | obj| status | date
---+----+--------+-----
1 | 1 | green | 2013
2 | 1 | green | 2014
3 | 1 | yellow | 2015
4 | 1 | orange | 2016 <- Last status of 1
5 | 2 | green | 2013
6 | 2 | green | 2014 <- Last status of 2
7 | 3 | green | 2010
8 | 3 | red | 2012 <- Last status of 3
I would need to get an output like that:
obj| status | date
---+--------+-----
1 | orange | 2016
2 | green | 2014
3 | red | 2012
text: The output shows the latest status of ech obj.
I hope somebody can help me..

A simple correlated subquery in the where clause does the trick:
select obj, status, date
from t
where t.date = (select max(t2.date) from t t2 where t2.status = t.status);

select obj, status, date
from t
where t.date = (select max(t2.date) from t t2 where t2.Obj= t.Obj);

Related

How to filter a table based on a specific column value of another column?

Hello I have a table here
---------------------
ID | PARTY | Name.Id
---------------------
1 | IND | 12
2 | IND | 13
3 | CUST | 14
4 | CUST | 15
5 | CUST | 16
6 | IND | 17
---------------------
I want to return the whole table but filter 'CUST' which has value 15 and 16 in the column 'Name.Id'
The result should look something like this
---------------------
ID | PARTY | Name.Id
---------------------
1 | IND | 12
2 | IND | 13
3 | CUST | 14
4 | IND | 17
---------------------
I tried using where statement on the 'Name.Id' but it returns only those rows which has a value 15 and 16.
whole table but filter 'CUST' which has value 15 and 16 in the column 'Name.Id'
It sounds like you want a where clause like:
WHERE NOT (party = 'CUST' and name.id IN(15,16))
But CUST seems redundant from your sample data, i.e. you could get away with simplifying it to just WHERE name.id NOT IN (15,16)
Can you give this a whirl?
select *
from t
where (PARTY, Name.Id) not in (
select 'CUST', 15
union
select 'CUST', 16
)
select *
from t
where Party not in
(select Party from t
where Party="CUST"
and (Name.Id=15 or Name=16));
I think I got the solution here
select *
from t
where Party <> 'CUST'
or (Party = 'CUST'
and Name.Id = 14))

subtract 2 DB rows from each other for each unique partner_ID? MYSQL

I have a MYSQL table where I need to get to subtract values from 2 different rows.
This is my DB table:
Tablename: ext_partnertotals
| Partner_ID | Partnername | Month | Year | Total |
|------------|-------------|-------|------|-------|
| 1 | Partner 1 | 1 | 2018 | 10 |
| 1 | Partner 1 | 2 | 2018 | 12 |
| 2 | Partner 2 | 1 | 2018 | 18 |
| 2 | Partner 2 | 2 | 2018 | 12 |
It should get this with a query:
| Partner_ID | Partnername | up/down |
|------------|-------------|---------|
| 1 | Partner 1 | +2 |
| 2 | Partner 2 | -6 |
I need to get the Subtract value of 2 different months for each Partner.
Every Partner has a tablerow for each month and a value for that month.
Now I need to get If they went up or went down in value since the month before.
Can someone write me a query?
Since you're unable to improve your terrible schema, I recommend you use a (very ugly/hard to maintain and very slow) correlated subquery:
SELECT Partner_ID, Partnername, Year, Month, Total - (
SELECT Total
FROM ext_partnertotals AS prev
WHERE prev.Partner_ID = cur.Partner_ID AND CASE cur.Month
WHEN 1 THEN prev.Year = cur.Year - 1 AND prev.Month = 12
ELSE prev.Year = cur.Year AND prev.Month = cur.Month - 1
END
) AS `up/down` FROM ext_partnertotals AS cur
See it on sqlfiddle.

SQL insert into select from - insert the id instead of the data

I need to populate my fact table with data from lds_placement table. I have selected the records and here is what it looks like:
fk1_account_id | fk3_job_role_id | salary | no_of_placements | YEAR
---------------------------------------------------------------------
10 | 3 | 165000 | 5 | 2010
10 | 3 | 132000 | 4 | 2011
10 | 3 | 132000 | 4 | 2012
20 | 2 | 990000 | 3 | 2010
20 | 2 | 132000 | 2 | 2011
20 | 2 | 132000 | 2 | 2012
I want to insert time_id from a different table called time_dim into the column year and not the actual year itself.
The time_dim table looks like this:
time_id | year
---------------
5 | 2015
1 | 2013
2 | 2010
3 | 2014
4 | 2012
6 | 2011
I need to insert into "year" column is actually:
year
2
6
4
2
6
4
Please give me the way to insert time_id instead of year in the table.
Here is the code I used to select the top-most table.
SELECT
fk1_account_id,
fk3_job_role_id,
Sum(actual_salary) AS salary,
Count(1) AS no_of_placements,
MAX(EXTRACT(YEAR FROM plt_estimated_end_date)) AS year
FROM lds_placement
GROUP BY fk1_account_id, fk3_job_role_id, EXTRACT(YEAR FROM plt_estimated_end_date)
ORDER BY fk1_account_id;
Use a left join if you want to capture records where year doesn't exist in time_dim. Else use inner_join.
select t.fk1_account_id,t.fk3_job_role_id,t.salary,t.no_of_placements
,d.time_id
from
(SELECT fk1_account_id, fk3_job_role_id, Sum(actual_salary) as salary, Count(1) as no_of_placements, MAX(EXTRACT(YEAR FROM plt_estimated_end_date)) AS YEAR
FROM lds_placement
GROUP BY fk1_account_id, fk3_job_role_id, EXTRACT(YEAR FROM plt_estimated_end_date)
)t
left join time_dim d
on t.year=d.year
order by t.fk1_account_id

SELECT all the latest non null records available based on date range in another table

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.

Mysql Queue Start/End time

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';