Remove duplicate column value - sql

Considering my table
+----+------+--------+----------+
| ID | Name | Salary | Month |
+----+------+--------+----------+
| 1 | a | 5000 | Jan |
| 2 | b | 5500 | Jan |
| 3 | b | 5300 | Feb |
| 4 | b | 5300 | Mar |
| 5 | b | 5300 | Apr |
| 6 | b | 5300 | May |
| 7 | b | 5300 | June |
| 8 | b | 5300 | July |
+----+------+--------+----------+
I need to display
+----+------+--------+----------+
| ID | Name | Salary | Month |
+----+------+--------+----------+
| 1 | a | 5000 | Jan |
| 2 | b | 5500 | Jan |
| 3 | | 5300 | Feb |
| 4 | | 5300 | Mar |
| 5 | | 5300 | Apr |
| 6 | | 5300 | May |
| 7 | | 5300 | June |
| 8 | | 5300 | July |
+----+------+--------+----------+
Can any1 help

I'm assuming the results are sorted by the name column (and probably then the salary?), you could use the analytic function ROW_NUMBER to single out the first one, and only print that one out.
You may want to tweak the query around a bit, but here's the main idea:
SELECT id, CASE rn WHEN 1 THEN name ELSE null END, salary, month
FROM (SELECT id, name, salary, month,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY salary) AS rn
FROM some_table)
ORDER BY name, rn

Please try below query for MS Sql server:
select
a.ID,
case when a.Name=b.Name then NULL else a.Name end Name,
a.Salary,
a.[Month]
from YourTable a left join YourTable b
on a.ID=b.ID+1

Related

How to update table 2 from the inserted data in table 1?

Can you help me on what query I to to update one table with data from another.
I have 2 tables for example:
tbl_med_take
| id | name | med | qty |
---------------------------------
| 1 | jayson | med2 | 3 |
| 2 | may | med2 | 4 |
| 3 | jenny. | med3 | 6 |
| 4 | joel. | med3 | 4 |
tbl_med
| id | med | stocks |
-----------------------------
| 1 | med1 | 20 |
| 2 | med2 |. 17 |
| 3 | med3 | 24 |
The output that I want in tbl_med:
tbl_med
| id | med | stocks |
-----------------------------
| 1 | med1 | 20 |
| 2 | med2 |. 10 |
| 3 | med3 | 14 |
First get the total consumed from med_tbl_take using
select med,sum(quantity) as total from tbl_med_take group by med
Then you can left join with your med_tbl and subtract.
select m.id,m.med,(m.stocks-ISNULL(n.total,0)) from tbl_med m
left join
(select med,sum(quantity) as total from tbl_med_take group by med) n
on m.med=n.med
CHECK DEMO HERE

Query Different Condition With 1 Column

I have table like :
+-------+--------+----------+------------+-------+
| cd_hs | cd_cnt | name_cnt | dates | value |
+-------+--------+----------+------------+-------+
| 1 | 1 | aaa | 2018-06-01 | 50 |
| 1 | 2 | bbb | 2018-07-01 | 150 |
| 1 | 3 | ccc | 2018-08-01 | 20 |
| 1 | 1 | aaa | 2018-06-02 | 40 |
| 1 | 2 | bbb | 2018-07-02 | 70 |
| 1 | 3 | ccc | 2018-08-02 | 80 |
+-------+--------+----------+------------+-------+
Actually I have more data but I am just show the sample and what I want to do is
I want to group by cd_hs, name_cnt and based on year in dates column and do sum(value) but I have the 2 condition. First is to show value with condition cd_cnt with 1 and 2 and second condition cd_cnt without 1 and 2 so meaning I have much value other than 1 and 2 and do aliasing as other in one column
Expected Result :
+-------+------+----------+-------------+
| cd_hs | year | name_cnt | total_value |
+-------+------+----------+-------------+
| 1 | 2018 | aaa | 90 |
| 1 | 2018 | bbb | 220 |
| 1 | 2018 | other | 100 |
+-------+------+----------+-------------+
how can I do that? I am new in query and don't know what to do..
Your question is a bit confusing considering your spec doesn't seem to exactly line up with what you requested.
If the sample result you've provided is actually what you're looking for, a simple SUM and GROUP BY should do the trick here:
SELECT cd_hs, EXTRACT(YEAR from dates) as year, name_cnt, SUM(value_)
FROM foo
GROUP BY cd_hs, EXTRACT(YEAR from dates), name_cnt
Result:
| cd_hs | year | name_cnt | sum |
|-------|------|----------|-----|
| 1 | 2018 | aaa | 90 |
| 1 | 2018 | bbb | 220 |
| 1 | 2018 | ccc | 100 |
SQLFiddle
Since you mentioned you wanted two different totals with two separate conditions, you could use JOIN in conjunction with some well-crafted subqueries:
SELECT a.cd_hs, EXTRACT(YEAR FROM a.dates), a.name_cnt, COALESCE(b.total_a, 0) as "Total A", COALESCE(c.total_b, 0) as "Total B"
FROM foo a
LEFT JOIN (
SELECT b.cd_hs, b.name_cnt, EXTRACT(YEAR FROM b.dates), SUM(value_) as total_a
FROM foo b
WHERE b.cd_cnt NOT IN (1, 2)
GROUP BY b.cd_hs, b.name_cnt, EXTRACT(YEAR from b.dates)
) b ON a.cd_hs = b.cd_hs AND a.name_cnt = b.name_cnt
LEFT JOIN (
SELECT c.cd_hs, c.name_cnt, EXTRACT(YEAR FROM c.dates), SUM(value_) as total_b
FROM foo c
WHERE c.cd_cnt IN (1, 2)
GROUP BY c.cd_hs, c.name_cnt, EXTRACT(YEAR from c.dates)
) c ON a.cd_hs = c.cd_hs AND a.name_cnt = c.name_cnt
This particular solution is readable and will get you to the correct end result but will most likely not be scalable in its current form.
Result:
| cd_hs | date_part | name_cnt | Total A | Total B |
|-------|-----------|----------|---------|---------|
| 1 | 2018 | aaa | 0 | 90 |
| 1 | 2018 | bbb | 0 | 220 |
| 1 | 2018 | ccc | 100 | 0 |
| 1 | 2018 | aaa | 0 | 90 |
| 1 | 2018 | bbb | 0 | 220 |
| 1 | 2018 | ccc | 100 | 0 |
SQLFiddle

Get the Id of the matched data from other table. No duplicates of ID from both tables

Here is my table A.
| Id | GroupId | StoreId | Amount |
| 1 | 20 | 7 | 15000 |
| 2 | 20 | 7 | 1230 |
| 3 | 20 | 7 | 14230 |
| 4 | 20 | 7 | 9540 |
| 5 | 20 | 7 | 24230 |
| 6 | 20 | 7 | 1230 |
| 7 | 20 | 7 | 1230 |
Here is my table B.
| Id | GroupId | StoreId | Credit |
| 12 | 20 | 7 | 1230 |
| 14 | 20 | 7 | 15000 |
| 15 | 20 | 7 | 14230 |
| 16 | 20 | 7 | 1230 |
| 17 | 20 | 7 | 7004 |
| 18 | 20 | 7 | 65523 |
I want to get this result without getting duplicate Id of both table.
I need to get the Id of table B and A where the Amount = Credit.
| A.ID | B.ID | Amount |
| 1 | 14 | 15000 |
| 2 | 12 | 1230 |
| 3 | 15 | 14230 |
| 4 | null | 9540 |
| 5 | null | 24230 |
| 6 | 16 | 1230 |
| 7 | null | 1230 |
My problem is when I have 2 or more same Amount in table A, I get duplicate ID of table B. which should be null. Please help me. Thank you.
I think you want a left join. But this is tricky because you have duplicate amounts, but you only want one to match. The solution is to use row_number():
select . . .
from (select a.*, row_number() over (partition by amount order by id) as seqnum
from a
) a left join
(select b.*, row_number() over (partition by credit order by id) as seqnum
from b
)b
on a.amount = b.credit and a.seqnum = b.seqnum;
Another approach, I think simplier and shorter :)
select ID [A.ID],
(select top 1 ID from TABLE_B where Credit = A.Amount) [B.ID],
Amount
from TABLE_A [A]

Grouping by a column to compare values between similar rows

I'm trying to turn this
+----+---------+-------------------+-----------+
| id | year | desc | amount |
+----+---------+-------------------+-----------+
| 1 | 2017 | car | 500 |
| 2 | 2017 | car | 550 |
| 1 | 2018 | car | 490 |
| 2 | 2018 | car | 550 |
| 1 | 2017 | house | 200 |
| 2 | 2017 | house | 300 |
| 1 | 2018 | house | 210 |
| 2 | 2018 | house | 320 |
| 1 | 2019 | house | 290 |
| 2 | 2019 | house | 325 |
+----+---------+-------------------+-----------+
Into something like this
+----+---------+---------+-------------------+-----------+-----------+
| id | year_0 | year_1 | desc | amount_0 | amount_1 |
+----+---------+---------+-------------------+-----------+-----------+
| 1 | 2017 | 2018 | car | 500 | 490 |
| 2 | 2017 | 2018 | car | 550 | 550 |
| 1 | 2017 | 2018 | house | 200 | 210 |
| 2 | 2017 | 2018 | house | 300 | 320 |
+----+---------+---------+-------------------+-----------+-----------+
But I'm having difficulty getting the two years and two amounts to group by description.
You can achieve the result by applying join:
SELECT A.id,a.year year_0,b.year year_1, A.[desc], A.amount amount_0,B.amount amount_1
FROM
(SELECT * FROM YourTable WHERE Year= Datepart(year,GETDATE())-1) AS A
INNER JOIN
(SELECT * FROM YourTable WHERE Year= Datepart(year,GETDATE())) AS B
ON A.id=B.id AND A.[desc]=B.[desc]

Why do you need to include a field in GROUP BY when using OVER (PARTITION BY x)?

I have a table for which I want to do a simple sum of a field, grouped by two columns. I then want the total for all values for each year_num.
See example: http://rextester.com/QSLRS68794
This query is throwing: "42803: column "foo.num_cust" must appear in the GROUP BY clause or be used in an aggregate function", and I cannot figure out why. Why would an aggregate function using the OVER (PARTITION BY x) require the summed field to be in GROUP BY??
select
year_num
,age_bucket
,sum(num_cust)
--,sum(num_cust) over (partition by year_num) --THROWS ERROR!!
from
foo
group by
year_num
,age_bucket
order by 1,2
TABLE:
| loc_id | year_num | gen | cust_category | cust_age | num_cust | age_bucket |
|--------|-----------|------|----------------|-----------|-----------|-------------|
| 1 | 2016 | M | cash | 41 | 2 | 04_<45 |
| 1 | 2016 | F | Prepaid | 41 | 1 | 03_<35 |
| 1 | 2016 | F | cc | 61 | 1 | 05_45+ |
| 1 | 2016 | F | cc | 19 | 2 | 02_<25 |
| 1 | 2016 | M | cc | 64 | 1 | 05_45+ |
| 1 | 2016 | F | cash | 46 | 1 | 05_45+ |
| 1 | 2016 | F | cash | 27 | 3 | 03_<35 |
| 1 | 2016 | M | cash | 42 | 1 | 04_<45 |
| 1 | 2017 | F | cc | 35 | 1 | 04_<45 |
| 1 | 2017 | F | cc | 37 | 1 | 04_<45 |
| 1 | 2017 | F | cash | 46 | 1 | 05_45+ |
| 1 | 2016 | F | cash | 19 | 4 | 02_<25 |
| 1 | 2017 | M | cash | 43 | 1 | 04_<45 |
| 1 | 2017 | M | cash | 29 | 1 | 03_<35 |
| 1 | 2016 | F | cc | 13 | 1 | 01_<18 |
| 1 | 2017 | F | cash | 16 | 2 | 01_<18 |
| 1 | 2016 | F | cc | 17 | 2 | 01_<18 |
| 1 | 2016 | M | cc | 17 | 2 | 01_<18 |
| 1 | 2017 | F | cash | 18 | 9 | 02_<25 |
DESIRED OUTPUT:
| year_num | age_bucket | sum | sum over (year_num) |
|----------|------------|-----|---------------------|
| 2016 | 01_<18 | 5 | 21 |
| 2016 | 02_<25 | 6 | 21 |
| 2016 | 03_<35 | 4 | 21 |
| 2016 | 04_<45 | 3 | 21 |
| 2016 | 05_45+ | 3 | 21 |
| 2017 | 01_<18 | 2 | 16 |
| 2017 | 02_<25 | 9 | 16 |
| 2017 | 03_<35 | 1 | 16 |
| 2017 | 04_<45 | 3 | 16 |
| 2017 | 05_45+ | 1 | 16 |
You need to nest the sum()s:
select year_num, age_bucket, sum(num_cust),
sum(sum(num_cust)) over (partition by year_num) --WORKS!!
from foo
group by year_num, age_bucket
order by 1, 2;
Why? Well, the window function is not doing aggregation. The argument needs to be an expression that can be evaluated after the group by (because this is an aggregation query). Because num_cust is not a group by key, it needs an aggregation function.
Perhaps this is clearer if you used a subquery:
select year_num, age_bucket, sum_num_cust,
sum(sum_num_cust) over (partition by year_num)
from (select year_num, age_bucket, sum(num_cust) as sum_num_cust
from foo
group by year_num, age_bucket
) ya
order by 1, 2;
These two queries do exactly the same thing. But with the subquery it should be more obvious why you need the extra aggregation.