How to get data for below scenario? - sql-server

I have 4 tables.
Employee:
Id|emp_start_date|Public_id|
01|00-00-00 |001
02|00-00-00 |002
Person:
Id|Public_id|name|...
01|001 |aaaa|..
02|002 |bbbb|...
pay_info:
public_id|current_pay_year
001|2015
002|2015
Ni_table:
public_id|Ni_letter_code|Niable_pay|ni_a|ni_b|ni_c|ni_d|year
001 |A |890 |12 | 12 | 0 | 0 |2015
002 |A |500 |14 |14 |0 | 0 |2015
002 |A |600 |14 |14 |0 | 0 |2015
002 |B |400 |13 | 13 |0 |0 |2015
002 |B |500 |13 | 13 |0 |0 |2015
I want to get the Sum of niable_pay and all other columns by using ni_letter_code for the year 2015.
I want to get all the employees details for current pay year.
But When the employee has two ni letter code, then he should have 2 row for them.
Each row should have the addition value for the respective ni_code.
Expected output:
01|A| 890|12|12|0|0|2015
02|A|1100|25|28|0|0|2015
02|B| 900|26|26|0|0|2015
My query:
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
from
employee e
JOIN person P ON e.id=P.id
INNER JOIN pay_info PI ON PI.public_id = E.public_id
INNER JOIN Ni_table NI ON NI.public_id = E.public_id
AND NI.year = PI.current_pay_year

You seem to think that by stating
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
you get a result record per e.id, NI.Ni_letter_code and ni.year along with the desired sums.
This is not the case. SQL doesn't aggregate by non-aggregated columns implicitely. You must make the aggregation group explicit with GROUP BY. So in order to get one result record per e.id, NI.Ni_letter_code and ni.year you'd add:
group by e.id, NI.Ni_letter_code, ni.year
at the end of your query:
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
from
employee e
JOIN person P ON e.id=P.id
INNER JOIN pay_info PI ON PI.public_id = E.public_id
INNER JOIN Ni_table NI ON NI.public_id = E.public_id
AND NI.year = PI.current_pay_year
group by e.id, NI.Ni_letter_code, ni.year;

Related

Converting Data to Tenths and averaging values

so I have a table in thousandths of a mile like this:
id |fk |from |to |speed|score
1 |123|10.002|10.003|20 |10
2 |123|10.003|10.004|25 |11
3 |123|10.004|10.005|40 |44
4 |123|10.005|10.006|50 |23
5 |123|10.006|10.007|20 |54
6 |123|10.007|10.008|10 |24
7 |123|10.008|10.009|65 |24
8 |123|10.009|10.010|23 |24
9 |123|10.010|10.011|74 |56
10 |123|10.011|10.012|25 |43
11 |123|10.012|10.013|10 |76
12 |123|10.013|10.014|5 |10
...
I need to convert the thousandth mile table to tenths of a mile and take average of speed and score like this:
id |fk |from |to |Avgspeed|Avgscore
1 |123|10.002|10.012|35.2 |31.3
10 |123|10.012|... |... |...
I came up with this query to get the tenth of a mile:
select CASE WHEN rn=1 then 1
when rn%10=0 then 1
else 0 end chk,x.* from
(
select row_number() over (partition by fk order by fk,from) rn,* from dbo.Thous_Data
)x
This gives me
id |fk |from |to |speed|score|chk|rn
1 |123|10.002|10.003|20 |10 |1 |1
2 |123|10.003|10.004|25 |11 |0 |2
3 |123|10.004|10.005|40 |44 |0 |3
4 |123|10.005|10.006|50 |23 |0 |4
5 |123|10.006|10.007|20 |54 |0 |5
6 |123|10.007|10.008|10 |24 |0 |6
7 |123|10.008|10.009|65 |24 |0 |7
8 |123|10.009|10.010|23 |24 |0 |8
9 |123|10.010|10.011|74 |56 |0 |9
10 |123|10.011|10.012|25 |43 |1 |10
11 |123|10.012|10.013|10 |76 |0 |11
12 |123|10.013|10.014|5 |10 |0 |12
...
Not sure how to proceed with getting the averages and setting up the from and to correctly. Any ideas appreciated.
Something like this?
SELECT 10 * FLOOR(id / 10) , AVG(speed), MIN( [from] ) , MAX( [to])
FROM dbo.Thous_Data
GROUP BY 10 * FLOOR(id / 10);
The way I was able to do it was by starting the count from 0 so that the brackets would be accurate:
with cte as
(select CASE WHEN rn=0 then 1
when rn%10=0 then 1
else 0 end chk,x.*
from
(
select ROW_NUMBER() over (partition by fk order by fk,from)-1 rn,* from dbo.Thous_Data
)x
)
,cte2 as(
SELECT
distinct fk,to,from,
SUM([Chk]) OVER (PARTITION BY fk ORDER BY to,from) AS Groups
FROM cte
)
Select distinct fk,
Min(from) over (partition by fk,groups) from_
,Max(to) over (partition by fk,groups) to_
,avg(speed) over (partition by fk,groups) Aspeed
,avg(score) over (partition by fk,groups) Ascore
from
cte2

How to : update column with sum column in same table in SQL Server 2014?

Before table data:
-----------------------
|ID |WORK|VALUE|TOTAL|
-----------------------
|ID1|WRITE |10 | |
|ID1|TYPE |5 | |
|ID2|READ |25 | |
|ID2|SCAN |30 | |
|ID3|PRINT |15 | |
|ID4|SETTING|20 | |
|ID5|REPAIR |5 | |
|ID5|MAINTE |25 | |
|ID5|MONITOR|20 | |
Total is sum value from same id
ID1 10+5
ID2 25+30
ID3 15
ID4 20
ID5 50
For now I use the insert method with create table data2 (ID,TOTAL)
INSERT INTO DATA2(DATA2.ID, DATA2.TOTAL)
SELECT DATA.ID, SUM (DATA.VALUE) AS TOTAL
FROM DATA
GROUP BY DATA.ID
Then I do SELECT JOIN FROM DATA2 AND DATA
After table data
-----------------------
|ID |WORK|VALUE|TOTAL|
-----------------------
|ID1|WRITE |10 |15 |
|ID1|TYPE |5 |15 |
|ID2|READ |25 |55 |
|ID2|SCAN |30 |55 |
|ID3|PRINT |15 |15 |
|ID4|SETTING|20 |20 |
|ID5|REPAIR |5 |50 |
|ID5|MAINTE |25 |50 |
|ID5|MONITOR|20 |50 |
To update the value total to table, you need to have the column..
alter table tblname
add total int
If this is not a one time approach,i would recommend creating a view like below
create view somename
as
select id,work,value,
sum(value) over (partition by id ) as total
from tabel
if you want to update table as one time excercise
;with cte
as
(select id,work,value,
sum(value) over (partition by id ) as total1
from tablename
)
update t
set t.total=c.total1
from cte c
join tablename t
on t.id=c.id
Another way to update the total.
UPDATE T1
SET T1.TOTAL=T2.TOTAL
FROM YOUT_TABLE T1
JOIN (
SELECT ID,SUM(VALUE) AS TOTAL
FROM YOUR_TABLE
GROUP BY ID
) T2 ON T1.ID=T2.ID
DEMO

Sum up delivered companies for every customer(ID)

I'm back in action ;) This time I have a pretty heavy task (I think).
Here's what I got:
|customerID ||company |compdel |Street |Code |Date 1 |Date 2 |
+-------------------------------+--------------------------------------+
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |01.01.2015 |01.08.2015 |
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |13.04.2015 |01.12.2015 |
|1 ||Example1 |DELExam2|DEL St.1|0212 |13.03.2015 |09.07.2015 |
|1 ||Example1 |DELExam3|REF Wy.1|9875 |26.05.2015 |16.09.2015 |
|2 ||Example2 |DELExam4|REG St.1|6754 |21.02.2015 |16.05.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.03.2015 |06.08.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.01.2015 |06.02.2015 |
I want to show for every customerID every delivered company (compdel) summed in one line with the earliest date in Date 1 and the newest Date in Date 2. To make it easier to understand, I want this result:
|customerID ||company |compdel |Street |Code |Date 1 |Date 2 |
+-------------------------------+--------------------------------------+
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |01.01.2015 |01.12.2015 |
|1 ||Example1 |DELExam2|DEL St.1|0212 |13.03.2015 |09.07.2015 |
|1 ||Example1 |DELExam3|REF Wy.1|9875 |26.05.2015 |16.09.2015 |
|2 ||Example2 |DELExam4|REG St.1|6754 |21.02.2015 |16.05.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.01.2015 |06.08.2015 |
I tried it already with this select-Statement but it won´t work: I know, that this can only be a part of the answer....
SELECT *
FROM
(SELECT
customerID, company, compdel, Street, Code, Date 1, Date 2,
ROW_NUMBER() OVER(PARTITION BY compdel ORDER BY customerID) rn
FROM
table 1) as Y
WHERE
rn = 1
Use GROUP BY with distinct values (customerId, company etc.) and MIN and MAX for dates
SELECT CustomerId
, Company
, CompDel
, Street
, Code
, MIN(Date1) As EarliestDate1
, MAX(Date2) AS NewestDate2
FROM YourTable
GROUP BY CustomerId, Company, CompDel, Street, Code

How to get the count of each distinct value in Multiple columns and get the result in separate columns?

I need the following table to be queried to get the result given below the table.
Table:
----------------------------------
| Name | Age | slot |
|-------|--------|---------------|
|A |20 | 1 |
|B |30 | 2 |
|C |30 | 1 |
|D |20 | 1 |
|E |40 | 2 |
|F |40 | 3 |
|G |50 | 3 |
----------------------------------
Result:
-------------------------------------------
|Age |Age_Count |Slot |Slot_Count|
-------------------------------------------
|20 | 2 |1 |3 |
-------------------------------------------
|30 | 2 |2 |2 |
-------------------------------------------
|40 | 2 |3 |2 |
-------------------------------------------
|50 | 1 |
-----------------------
While searching stackoverflow i found this question for single column question and there is [this link for multiple columns] (get the count of each distinct value in "Multiple" columns) question. The answers from the second link (for the multiple coulmn's distinct count) is displayed under a single column and my requirement is i guess quite different from the answers posted there.
Thanks in advance
Your request is kind of odd. Are you sure you want that?
If so, this may help:
SET #x:=0,#y:=0,#m:=0,#n:=0;
SELECT
DISTINCT age,age_count, slot,slot_count
FROM (
SELECT
age, age_count, slot, slot_count
FROM (
SELECT
#x:=#x + 1 AS aid, age, COUNT(*) age_count
FROM
slots
GROUP BY age
) a
LEFT JOIN (
SELECT
#y:=#y + 1 AS sid, slot, COUNT(*) slot_count
FROM
slots
GROUP BY slot
) s ON a.aid = s.sid
UNION
SELECT
age, age_count, slot, slot_count
FROM (
SELECT
#m:=#m + 1 AS aid, slot, COUNT(*) slot_count
FROM
slots
GROUP BY slot
) a
LEFT JOIN (
SELECT
#n:=#n + 1 AS sid, age, COUNT(*) age_count
FROM
slots
GROUP BY age
) s ON a.aid = s.sid
) a
If you know for sure that you have more unique ages than unique slots , or opposite, you can get ride of messy union.

SQLite join selection from the same table using reference from another table

I have two tables:
table: points
|key_id | name | x | y |
------------------------
|1 | A |10 |20 |
|2 | A_1 |11 |21 |
|3 | B |30 |40 |
|4 | B_1 |31 |42 |
table: pairs
|f_key_p1 | f_key_p2 |
----------------------
|1 | 2 |
|3 | 4 |
Table 'pairs' defines which rows in table 'points' should be paired.
How can I query database to select paired rows?
My desired query result would be like this:
|name_1|x_1|x_2|name_2|x_2|y_2|
-------------------------------
|A |10 |20 |A_1 |11 |21 |
|B |30 |40 |B_1 |31 |41 |
You just join from points to pairs and from pairs again to points. E.g. like this:
SELECT
p1.name AS name_1, p1.x AS x_1, p1.y AS y_1,
p2.name AS name_2, p2.x AS x_2, p2.y AS y_2
FROM points as p1
INNER JOIN pairs ON (p1.key_id = pairs.f_key_p1)
INNER JOIN points AS p2 ON (pairs.f_key_p2 = p2.key_id);
Using the INNER JOIN (abbr. JOIN) combines rows only if there is a match in both tables.
select p1.name name_1, p1.x x_1, p1.y y_1, p2.name name_2, p2.x x_2, p2.y y_2
from points p1 join pairs p on p1.key_id = p.f_key_p1
join points p2 on p2.key_id = p.f_key_p2

Resources