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

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

Related

Select N previous and M next items around current item id

I have a table with photos
id | year| comm_count
0 2015 1
1 2016 2
2 2017 5
3 2018 7
4 2019 1
5 2020 9
6 2021 1
7 2022 1
I select photo with a given id, somewhere in the middle of all photos. For example like this:
SELECT *
FROM photo
WHERE year > '2017'
ORDER BY comm_count DESC, year DESC
This will give me:
5,3,7,6,4
This gives me list of all photos. Now, I write this list on my web, but user can click on one certain photo. After that, detailed page opens. But from this detailed page, I would like to be able to go to "next" M and "previous" N photos. This means, I need to select neihboring IDs based on currenttly selected one. How can this be done?
Now I select id = 7 and I want neighbors to be:
prev: 5,3 and next: 6,4. How can this be selected?
SqlFiddle - http://sqlfiddle.com/#!9/4f3f42/4/0
I cannot run the same query and filter results in PHP, because query can contain LIMITS (eg. with LIMIT 2, 4 I still the need correct neighbors)
Once you have the year and comm_count values for the selected row with id=7, you can make two simple queries:
SELECT * FROM photo
WHERE year > 2017 AND (comm_count = 1 AND year <= 2022 OR comm_count < 1)
ORDER BY comm_count DESC, year DESC LIMIT 3 OFFSET 1
+----+------+------------+
| id | year | comm_count |
+----+------+------------+
| 6 | 2021 | 1 |
| 4 | 2019 | 1 |
+----+------+------------+
SELECT * FROM photo
WHERE year > 2017 AND (comm_count = 1 AND year >= 2022 OR comm_count > 1)
ORDER BY comm_count ASC, year ASC LIMIT 3 OFFSET 1;
+----+------+------------+
| id | year | comm_count |
+----+------+------------+
| 3 | 2018 | 7 |
| 5 | 2020 | 9 |
+----+------+------------+
If you use MySQL 8.0, you can use the LAG() and LEAD() functions.
SELECT id, year,
LAG(id, 1) OVER w AS next,
LAG(id, 2) OVER w AS next_next,
LEAD(id, 1) OVER w AS prev,
LEAD(id, 2) OVER w AS prev_prev
FROM photo
WHERE year > 2017
WINDOW w AS (ORDER BY comm_count DESC, year DESC)
+----+------+------+-----------+------+-----------+
| id | year | next | next_next | prev | prev_prev |
+----+------+------+-----------+------+-----------+
| 5 | 2020 | NULL | NULL | 3 | 7 |
| 3 | 2018 | 5 | NULL | 7 | 6 |
| 7 | 2022 | 3 | 5 | 6 | 4 |
| 6 | 2021 | 7 | 3 | 4 | NULL |
| 4 | 2019 | 6 | 7 | NULL | NULL |
+----+------+------+-----------+------+-----------+

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.

Creating a crosstab query in MySQL

I have a MySQL table that tracks certain totals by both hour of the day and various locations. I am trying to create a query that will total not only each column, but also each row. The query I have so far totals each column, but I can't figure out how to get a total for each row as well.
This is my query:
SELECT * FROM
(SELECT IFNULL(hour,"Total") as hour, SUM(location1), SUM(location2), SUM(location3), SUM(location4), SUM(location), FROM counts WHERE ay = 'AY1617' GROUP BY hour WITH ROLLUP) as crossdata
ORDER BY FIELD (hour,'8:00am','9:00am','10:00am','11:00am','12:00pm','1:00pm','2:00pm','3:00pm','4:00pm','5:00pm','6:00pm','7:00pm','8:00pm','9:00pm','10:00pm','11:00pm')
This is ultimately what I want the output to look like:
hour location1 location2 location3 location4 totals
8am 4 3 2 1 10
9am 1 2 2 1 6
10am 2 3 2 3 10
totals 7 8 6 5 26
How can I achieve this?
For what it's worth, this is not a crosstab query. You aren't pivoting rows to columns.
I tried this query and got the result you want:
SELECT IFNULL(hour, 'Total') AS hour,
SUM(location1) AS location1,
SUM(location2) AS location2,
SUM(location3) AS location3,
SUM(location4) AS location4,
SUM(location1)+SUM(location2)+SUM(location3)+SUM(location4) AS totals
FROM counts
WHERE ay = 'AY1617'
GROUP BY hour WITH ROLLUP;
You should really use the TIME data type instead of strings for the hour. Then it just sorts correctly.
+----------+-----------+-----------+-----------+-----------+--------+
| hourt | location1 | location2 | location3 | location4 | totals |
+----------+-----------+-----------+-----------+-----------+--------+
| 08:00:00 | 4 | 3 | 2 | 1 | 10 |
| 09:00:00 | 1 | 2 | 2 | 1 | 6 |
| 10:00:00 | 2 | 3 | 2 | 3 | 10 |
| Total | 7 | 8 | 6 | 5 | 26 |
+----------+-----------+-----------+-----------+-----------+--------+

2 columns. Merge duplicate values of A, sum duplicate values of B

I have a table that has 2 columns with data like this (from 1950 to 2015):
| Year | Count |
| 1994 | 10 |
| 1994 | 49 |
| 1994 | 2 |
| 1995 | 13 |
| 1995 | 6 |
I want my query result to be:
| Year | Count |
| 1994 | 61 |
| 1995 | 19 |
Things I have tried:
I began with a simple query like SELECT SUM(Count) FROM 'population' WHERE 'Year' = '1994' which was fine to bring a specific year but I wanted to fill an array with the population of every year in the database.
Doing something like SELECT Year, SUM(Count) FROM 'population' is closer to what I want except it just shown the first year only.
I'm not sure what terms I need to search up to get close to my answer. Union? I tried applying it but I just blerghed.
Try to use
SELECT year,SUM(Count) FROM 'population' group by year

Intersection of two MySql queries

I have a table where each data has a date when it was inserted in form of two columns, year and week:
+------+------+-------+
| Week | Year | Value |
+------+------+-------+
| 1 | 2014 | 5 |
| 5 | 2014 | 23 |
| 6 | 2014 | 12 |
| 7 | 2014 | 43 |
| 8 | 2014 | 4 |
| 9 | 2014 | 2 |
| 26 | 2013 | 21 |
| 27 | 2013 | 17 |
| 28 | 2013 | 42 |
| 31 | 2013 | 5 |
| ... | ... | .. |
+------+------+-------+
I need a query to get data that was inserted between two dates (year, week). I guess that it should be alternative to intersection of two queries, one with a starting date and the second with ending data, but I can't get it to work. Any help or sugestion?
Here is my shot but INTERSECT is not supported in MySql:
(SELECT SUM(Duration), Week, Type, Year
FROM UP26rotordowntime
WHERE (Year>=2013)
AND (Week >=01)
GROUP BY Week)
INTERSECT
(SELECT SUM(Duration), Week, Type, Year
FROM UP26rotordowntime
WHERE (Year<=2014)
AND (Week <=14)
GROUP BY Week)
You can put simple logic in WHERE conditions and use (year,week) pairs for GROUP BY:
SELECT SUM(Duration), Week, Type, Year
FROM UP26rotordowntime
WHERE Year = 2005 AND Week >= 10
OR Year BETWEEN 2006 AND 2013
OR Year = 2014 AND Week <= 14
GROUP BY Year,Week
If you have id the query is very simple:
SELECT SUM(Duration), Week, Type, Year FROM UP26rotordowntime
WHERE ID IN (
SELECT ID FROM UP26rotordowntime WHERE (Year>=2013) AND (Week >=01) )
OR ID IN (
SELECT ID FROM UP26rotordowntime WHERE (Year<=2014) AND (Week <=14))
GROUP BY Week
This should return you the intersect you need