How to remove duplicate values from a query - postgresql

I have the following issue, I need to remove duplicate values from a specific column I query. No deleting!(ClassID)
SchoolNo
Schoolyear
Schoolgrade
Classname
ClassId
65432
2001
5
ab
441
65432
2001
5
cd
442
65432
2001
6
a
443
65432
2001
6
b
444
56838
2001
5
ab
445
56838
2001
5
cd
446
56838
2001
6
ab
445
56838
2001
6
ef
447
12726
2001
5
ms
448
12726
2001
6
ms
448
If you look at the values of classId I have repeated class numbers because some special schools sometimes put 2 classes together for both grades. The problem is my query needs to show only 1 classid value. No repeats. Therefore we can remove any extra class that is repeated in value and only show for grade 5.
In other words my table should at end up looking like this.
SchoolNo
Schoolyear
Schoolgrade
Classname
ClassId
65432
2001
5
ab
441
65432
2001
5
cd
442
65432
2001
6
a
443
65432
2001
6
b
444
56838
2001
5
ab
445
56838
2001
5
cd
446
56838
2001
6
ef
447
12726
2001
5
ms
448
The code generally looks like this.
select schoolno,schoolyear,schoolgrade,classname,classId
from classgroup cg
How should I approach this?

maybe you can do it like this:
select
first_value(schoolno) over w,
first_value(schoolyear) over w,
first_value(schoolgrade) over w,
first_value(classname) over w,
first_value(classId) over w
FROM
classgroup
WINDOW w AS (PARTITION BY schoolno, schoolyear, classId ORDER BY schoolgrade);
You partition the data by schoolno, schoolyear and classId and order by schoolgrade then take only the first row of each partition.
Note: the syntax may be a bit off since I couldn't test it

Try this
select cg1.* from classgroup cg1
left join classgroup cg2 on (cg1."ClassId"=cg2."ClassId" and cg1."Schoolgrade"<cg2."Schoolgrade")
where cg2."Schoolgrade" is null
The output:

Related

How to calculate the amount spent for the last month in SQL?

I have a table transaction_details:
transaction_id
customer_id
item_id
item_number
transaction_dttm
7765
1
23
1
2022-01-15
1254
2
12
4
2022-02-03
3332
3
56
2
2022-02-15
7658
1
43
1
2022-03-01
7231
4
56
1
2022-01-15
7231
2
23
2
2022-01-29
I need to form a table of the following type customer_aggr:
customer_id
amount_spent_lm
top_item_lm
1
700
glasses
2
20000
notebook
3
100
cup
When calculating, it is necessary to take into account the current price at the time of the transaction (dict_item_prices). Customers who have not made purchases in the last month are not included in the final table. he last month is defined as the last 30 days at the time of the report creation.
There is also a table dict_item_prices:
item_id
item_name
item_price
valid_from_dt
valid_to_dt
23
phone 1
1000
2022-01-01
2022-12-31
12
notebook
5000
2022-01-02
2022-12-31
56
cup
50
2022-01-02
2022-12-31
43
glasses
700
2022-01-01
2022-12-31

Flatten one column keeping others in POSTGRESQL

I created a view which is presently giving the data like this:
practice_name message_type message_count
CHC ALOG_SYNC 1
CHC BULKNT 0
CHC PIE_SYNC 1
CHC PPRV_SYNC 1
CHC SYNC_PRACT 3
CHC SYNC_PROV 9
CHC SYNC_WTXT 3
CHC SYNC_XYZ 0
Midtown ALOG_SYNC 0
Midtown BULKNT 0
Midtown PIE_SYNC 0
Midtown PPRV_SYNC 0
Midtown SYNC_PRACT 3
Midtown SYNC_PROV 0
Midtown SYNC_WTXT 3
Midtown SYNC_XYZ 0
NextGen MedicalPractice ALOG_SYNC 0
NextGen MedicalPractice BULKNT 1
NextGen MedicalPractice PIE_SYNC 0
NextGen MedicalPractice PPRV_SYNC 0
NextGen MedicalPractice SYNC_PRACT 3
NextGen MedicalPractice SYNC_PROV 591
NextGen MedicalPractice SYNC_WTXT 3
NextGen MedicalPractice SYNC_XYZ 0
My View:
CREATE OR REPLACE VIEW sha.sha_export_queue_view AS
SELECT q3.practice_name,
q3.message_type,
q3.share_site_org_key,
COALESCE(q2.message_count, '0'::text) AS message_count
FROM ( SELECT q1.practice_name,
mt.message_type,
q1.share_site_org_key
FROM sha.message_types mt,
( SELECT DISTINCT jsonb_array_elements((ai.result_json -> 'Patient Portal Operational Information'::text) -> 'nxmd_export contents by message type'::text) ->> 'Practice Name'::text AS practice_name,
ai.share_site_org_key
FROM sha.sha_share_site_view ssv
LEFT JOIN ( SELECT mytable2.assessment_id,
mytable2.result_json,
mytable2.share_site_org_key,
mytable2.rnk
FROM ( SELECT assessment_info.assessment_id,
assessment_info.result_json,
assessment_info.share_site_org_key,
dense_rank() OVER (PARTITION BY assessment_info.share_site_org_key ORDER BY assessment_info.modified_datetime DESC) AS rnk
FROM sha.assessment_info
WHERE assessment_info.assessment_id = 8::numeric) mytable2
WHERE mytable2.rnk = 1) ai ON ssv.share_site_org_key = ai.share_site_org_key) q1) q3
LEFT JOIN ( SELECT jsonb_array_elements((ai.result_json -> 'Patient Portal Operational Information'::text) -> 'nxmd_export contents by message type'::text) ->> 'Practice Name'::text AS practice_name,
jsonb_array_elements((ai.result_json -> 'Patient Portal Operational Information'::text) -> 'nxmd_export contents by message type'::text) ->> 'Message Type'::text AS message_type,
jsonb_array_elements((ai.result_json -> 'Patient Portal Operational Information'::text) -> 'nxmd_export contents by message type'::text) ->> 'Message Count'::text AS message_count
FROM sha.sha_share_site_view ssv
LEFT JOIN ( SELECT mytable2.assessment_id,
mytable2.result_json,
mytable2.share_site_org_key,
mytable2.rnk
FROM ( SELECT assessment_info.assessment_id,
assessment_info.result_json,
assessment_info.share_site_org_key,
dense_rank() OVER (PARTITION BY assessment_info.share_site_org_key ORDER BY assessment_info.modified_datetime DESC) AS rnk
FROM sha.assessment_info
WHERE assessment_info.assessment_id = 8::numeric) mytable2
WHERE mytable2.rnk = 1) ai ON ssv.share_site_org_key = ai.share_site_org_key) q2 ON q3.message_type::text = q2.message_type AND q3.practice_name = q2.practice_name
ORDER BY q3.practice_name;
I want the second column to be flattened:
Practice Time Stamp <<message type 1>> <<message type 2>> <<message type 3>> <<message type 4 >> <<message type 5>> <<message type 6>> <<message type 7>> <<message type 8>>
Practice Name 1 21-12-2016 10:00 23 25 27 29 31 33 35 37
Practice Name 2 21-12-2016 10:00 24 26 28 30 32 34 36 38
Practice Name 3 21-12-2016 13:00 25 27 29 31 33 35 37 39
Practice Name 4 21-12-2016 13:00 26 28 30 32 34 36 38 40
Practice Name 5 24-12-2016 13:00 27 29 31 33 35 37 39 41
Practice Name 6 27-12-2016 13:00 28 30 32 34 36 38 40 42
Practice Name 7 30-12-2016 13:00 29 31 33 35 37 39 41 43
Practice Name 8 02-01-2017 13:00 30 32 34 36 38 40 42 44
Practice Name 1 05-01-2017 13:00 31 33 35 37 39 41 43 45
Practice Name 2 08-01-2017 13:00 32 34 36 38 40 42 44 46
Practice Name 3 11-01-2017 13:00 33 35 37 39 41 43 45 47
Is there any way I can achieve that?
Sorry for the little alignment issue.
The values are corresponding message type values
Sample for query (idea in comments to question):
SELECT
practice_name,
sum("ALOG_SYNC") AS "ALOG_SYNC",
sum("BULKNT") AS "BULKNT",
...
FROM (
SELECT
practice_name,
CASE WHEN q3.message_type = 'ALOG_SYNC' THEN sum(message_count) END AS "ALOG_SYNC",
CASE WHEN q3.message_type = 'BULKNT' THEN sum(message_count) END AS "BULKNT"
FROM
<your from + where clause>
) AS A
GROUP BY 1
Probably your query might be optimised.
Or you can use crosstab function (https://www.postgresql.org/docs/current/static/tablefunc.html)

Tableau: How to perform "Summarize totals except top 3"?

I have data something like below for the name of person and the total sales he/she made:
ABC1 34
ABC2 45
ABC3 78
ABC4 79
ABC5 23
ABC6 61
ABC7 34
ABC8 54
ABC9 90
I have to display the dashboard as below, top 3 sales guys and the overall total sales made by rest of the team as ROT which is 498 - (90 + 78 + 79) = 251 team:
ABC9 90
ABC4 79
ABC3 78
ROT 251
For the top sales made, I gave a filter by sales person name, with Limit condition as "Top 3". But I am struggling to display the ROI even in a separate worksheet. Any help is appreciated.
Right click on your dimension [Sales Guy] and choose Create/Set
Define the set by the Top N (either hard code it or use a parameter to change it easily) and call it [TopNSalesGuy]
Create a calculated field [TopNSalesGuysPlusOther] with the formular:
IF [TopNSalesGuy] THEN [Sales Guy] ELSE 'ROT' END
Use [TopNSalesGuysPlusOther] in your table/graph and you should have the top N sales guys by name and everythign else as 'ROT

TSQL 2008 Running total with previous months & years

I'm trying to get the Running total from the values from the previous months. And if the month is january I would like to get the total from the previous year and so forth.
I hope someone can help.
WITH CTE AS (SELECT COUNT(LZP.pv_zaaknummer) AS [Aantal LZP]
, YEAR(LZP.lzp_actief_vanaf) AS Jaar
, MONTH(LZP.lzp_actief_vanaf) AS Maand
FROM dm.crm_LZP_Vn_zaaktype_leefzorgplan_registrerenExtensionBase_hist AS LZP
WHERE LZP.LZP_actief_tot_LDTS > GETDATE()
GROUP BY YEAR(LZP.lzp_actief_vanaf)
, MONTH(LZP.lzp_actief_vanaf)
)
SELECT a.Jaar
, a.Maand
, a.[Aantal LZP]
, (
SELECT SUM(b.[Aantal LZP])
FROM CTE AS b
WHERE b.Jaar <= a.Jaar
) AS [Running Total 1]
, (
SELECT SUM(b.[Aantal LZP])
FROM CTE AS b
WHERE b.Jaar <= a.Jaar
AND b.Maand <= a.Maand
) AS [Running Total 2]
FROM CTE AS a
ORDER BY a.Jaar, a.Maand;
Results as of now, I'm getting the Totals per year and then the running totals per year:
Jaar Maand Aantal LZP Running Total 1 Running Total 2
2014 4 11 661 11
2014 5 52 661 63
2014 6 70 661 133
2014 7 76 661 209
2014 8 39 661 248
2014 9 86 661 334
2014 10 112 661 446
2014 11 120 661 566
2014 12 95 661 661
2015 1 57 3327 57
2015 2 109 3327 166
2015 3 196 3327 362
2015 4 200 3327 573
2015 5 169 3327 794
2015 6 233 3327 1097
2015 7 276 3327 1449
2015 8 224 3327 1712
2015 9 203 3327 2001
2015 10 291 3327 2404
2015 11 296 3327 2820
2015 12 412 3327 3327
2016 1 311 6062 368
2016 2 341 6062 818
2016 3 476 6062 1490
2016 4 440 6062 2141
2016 5 418 6062 2780
2016 6 500 6062 3583
2016 7 249 6062 4184
I would like it to be:
Running Total 3
11
63
133
209
248
334
446
566
661
718
827
1023
1223
1392
1625
1901
2125
2328
2619
2915
3327
3638
3979
4455
4895
5313
5813
6062
you could do it without subquery try
....................)
SELECT a.Jaar
, a.Maand
, a.[Aantal LZP],SUM([Aantal LZP]) over (order by jaar) [Running Total 1]
, SUM([Aantal LZP]) over (partition by jaar order by maand) [Running Total 2],
SUM([Aantal LZP]) over ( order by jaar,maand) [Running Total 3]
FROM CTE AS a
ORDER BY a.Jaar, a.Maand;
old version
SELECT a.Jaar
, a.Maand
, a.[Aantal LZP],(SELECT SUM(b.[Aantal LZP])
FROM CTE AS b
WHERE b.Jaar <= a.Jaar
) [Running Total 1],
(SELECT SUM(b.[Aantal LZP])
FROM CTE AS b
WHERE b.Jaar <= a.Jaar and Maand<=a.Maand
) [Running Total 2]
, (SELECT SUM(b.[Aantal LZP])
FROM CTE AS b
WHERE dateadd(year,jaar-1900,dateadd(month,maand-1,0)) <= dateadd(year,a.jaar-1900,dateadd(month,a.maand-1,0))
) [Running Total 3]
FROM CTE AS a
ORDER BY a.Jaar, a.Maand;
Found the Solution but now I must find to integrate it so it responds to my reportparameters Jaar and Maand
DECLARE #SalesTbl TABLE (Jaar int, Maand int, Aantal int, RunningTotal int)
DECLARE #Jaar int,
#Maand int,
#Aantal int,
#RunningTotal int
SET #RunningTotal = 0
DECLARE rt_cursor CURSOR
FOR
WITH CTE AS
(SELECT COUNT(LZP.pv_zaaknummer) AS [Aantal LZP]
, YEAR(LZP.lzp_actief_vanaf) AS Jaar
, MONTH(LZP.lzp_actief_vanaf) AS Maand
FROM dm.crm_LZP_Vn_zaaktype_leefzorgplan_registrerenExtensionBase_hist AS LZP
WHERE LZP.LZP_actief_tot_LDTS > GETDATE()
GROUP BY LZP.lzp_actief_vanaf
)
SELECT A.Jaar, A.Maand, SUM(A.[Aantal LZP])
FROM CTE AS A
GROUP BY Jaar, Maand
ORDER BY A.Jaar, A.Maand
OPEN rt_cursor
FETCH NEXT FROM rt_cursor INTO #Jaar, #Maand, #Aantal
WHILE ##FETCH_STATUS = 0
BEGIN
SET #RunningTotal = #RunningTotal + #Aantal
INSERT #SalesTbl VALUES (#Jaar, #Maand,#Aantal,#RunningTotal)
FETCH NEXT FROM rt_cursor INTO #Jaar, #Maand, #Aantal
END
CLOSE rt_cursor
DEALLOCATE rt_cursor
SELECT * FROM #SalesTbl

Using a join instead of subquery

For this question:
Get the pids of products ordered through any agent who makes at least one order for a customer in Kyoto. Use joins this time; no sub-queries.
I was able to get the answer using a subquery:
select distinct pid
from orders
where aid in (
select aid
from orders
where cid in(
select cid
from customers
where city = 'Kyoto'
)
)
I cannot figure out how to do this using only joins however.
This code returns the aid's that i need to get the pid's however i can't come up with a way to get them without using a sub query:
select distinct o.aid
from orders o, customers c
where o.cid = c.cid
and c.city = 'Kyoto'
Here are the two tables i am using:
Customers:
cid name city discount
c001 Tiptop Duluth 10.00
c002 Basics Dallas 12.00
c003 Allied Dallas 8.00
c004 ACME Duluth 8.00
c005 Weyland-Yutani Acheron 0.00
c006 ACME Kyoto 0.00
and Orders:
ordno mon cid aid pid qty dollars
1011 jan c001 a01 p01 1000 450.00
1013 jan c002 a03 p03 1000 880.00
1015 jan c003 a03 p05 1200 1104.00
1016 jan c006 a01 p01 1000 500.00
1017 feb c001 a06 p03 600 540.00
1018 feb c001 a03 p04 600 540.00
1019 feb c001 a02 p02 400 180.00
1020 feb c006 a03 p07 600 600.00
1021 feb c004 a06 p01 1000 460.00
1022 mar c001 a05 p06 400 720.00
1023 mar c001 a04 p05 500 450.00
1024 mar c006 a06 p01 800 400.00
1025 apr c001 a05 p07 800 720.00
1026 may c002 a05 p03 800 740.00