Case statement to for a table with and or conditions? - sql-server

I have a table name
Spend:
id value type date total
1 21 ar 3/3/2012 45
2 24 az 3/3/2012 55
3 25 az 3/3/2012 55
4 25 az 3/3/2012 45
5 25 ar 3/3/2012 45
Condition:
APR=(value=25 and type like 'ar') or(total=55)
How can i write case statement in select statement with out using #temp and cte's in single select statement.
The output of select statement must be
id value type date total APR
1 21 ar 3/3/2012 45 0
2 24 az 3/3/2012 55 1
3 25 az 3/3/2012 55 1
4 25 az 3/3/2012 45 0
5 25 ar 3/3/2012 45 1

Try this
SELECT id,value,type,date,total,APR,
CASE WHEN (value=25 and type like 'ar') OR (total=55) Then 1 ELSE 0 END AS [Apr]
FROM Table1
CASE

SELECT IIF((Value = 25 and type like 'ar') or (total=55)', 1, 0) AS APR, *
FROM Spend

Related

query max date of all customers that falls under a where condition

I would like to query the max date only of all customers that has a value of 25.
Table1
cust_id Date Value
1 2019-10-01 25
1 2019-10-19 35
1 2018-08-27 29
1 2019-07-09 35
1 2019-10-15 55
2 2019-09-26 45
2 2019-10-19 31
2 2019-07-19 8
2 2019-10-02 28
3 2019-09-02 36
3 2019-08-15 39
4 2019-10-15 37
4 2019-10-16 36
4 2018-11-18 27
wrote this query:
select
t1.value,
max(t1.date) as max_date
from table1 t1
where
(t1.date >= '2019-09-30 and t1.date <= 2019-10-31)
and t1.value > 25
group by t1.value
but I am getting:
cust_id Date Value
1 2019-10-01 25
1 2019-10-19 35
1 2019-10-15 55
2 2019-10-19 31
2 2019-10-02 28
4 2019-10-15 37
4 2019-10-16 36
would like to only see the last data entry that is over 25. Something like this:
cust_id Date Value
1 2019-10-19 35
2 2019-10-19 31
4 2018-11-16 36

SQL - Select non repeating columns

I have a table like
id name R_id mgr_id
----------------------------
61 a 22 1
62 a 22 2
62 b 23 1
63 c 24 4
63 b 22 3
64 c 25 3
and I would like to get the following result set
R_id mgr_id
--------------
22 1
23 1
24 4
25 3
I would like select repeating R_ids only once
I tried using this query but with not much success, can anyone help me.
SELECT DISTINCT R_id, mgr_id from DT
Perhaps something like this... WITH TIES clause in concert with Row_NUmber()
Example
Select Top 1 with ties
R_ID
,mgr_id
From #YourTable
Order By Row_Number() over (Partition By R_ID order by Mgr_id)
Returns
R_ID mgr_id
22 1
23 1
24 4
25 3

Postgresql select top 5 marks rows for every unique student id

This is one of my views called xyz:
ID | NAME |......Other Data... | Marks
1 A 100
1 A 100
1 A 99
1 A 95
1 A 94
1 A 94
1 A 94
1 A 91
1 A 87
1 A 86
2 B 100
2 B 94
2 B 93
2 B 90
2 B 89
2 B 89
2 B 87
2 B 86
3 C 100
3 C 98
3 C 98
3 C 97
3 C 92
3 C 91
3 C 90
The query I used to get this is something like this:
create or replace view xyz as
select *
from abc
where id in
(select id
from data)
order by id, mark desc, id;
And based on unique ids I want the top 5 rows:
ID | NAME |......Other Data... | Marks
1 A 100
1 A 100
1 A 99
1 A 95
1 A 94
2 B 100
2 B 94
2 B 93
2 B 90
2 B 89
3 C 100
3 C 98
3 C 98
3 C 97
3 C 92
I tried referring to this:
MySQL: Select top 5 rows based on ID and find Subtotal
But I wasn't able to do it. Could you please help?
You can use a windowed rank(), partitioned by each student name, and ordered by marks descending, to find the top 5 marks for each Student:
WITH cteRankedMarks AS
(
SELECT "ID", "NAME", "Marks",
rank() OVER (PARTITION BY "NAME"
ORDER BY "Marks" DESC) AS rank
FROM MyTable
)
SELECT "ID", "NAME", "Marks"
FROM cteRankedMarks
WHERE rank <= 5
ORDER BY "NAME", "Marks" DESC;
SqlFiddle here
Notes
If two or more marks have the same value vying for 5th place, then , then rank will return all such marks. If you don't want ties, then use row_number() instead of rank(). More about these here
Obviously, if a student doesn't have 5 marks, then fewer rows will be returned.

Spliting one row of record into multiple between two date

Can anybody help me out to do this:
My table data is like
Datefiled Field1 Field2 Field2 Field4
01-01-2012 ABC 10 15 17
01-04-2013 PQR 7 80 65
01-05-2014 XYZ 15 25 77
The output would look something like this
Month/Year Field1 Field2 Field2 Field4
01/2012 ABC 10 15 17
02/2012 ABC 10 15 17
03/2012 ABC 10 15 17
04/2012 ABC 10 15 17
.....
03/2013 ABC 10 15 17
04/2013 PQR 7 80 65
05/2013 PQR 7 80 65
06/2013 PQR 7 80 65
07/2013 PQR 7 80 65
.......
04/2014 PQR 7 80 65
05/2014 XYZ 15 25 77
Just create a calendar table, either one row per day or one row per month, and you can use a tally table (=virtual, constructed for example with a CTE) too and do something like this:
select
*
from
calendar c
cross apply (
select top 1 *
from yourtable y
where y.Datefiled < c.calendardate
order by Datefiled desc
) y
;WITH datat as (
SELECT *
FROM (VALUES
('2012-01-01', 'ABC', 10, 15, 17),('2012-12-12', 'LKJ', 16, 12, 13),
('2013-01-15', 'CVB', 16, 11, 19),('2013-04-01', 'PQR', 7, 80, 65),
('2014-04-24', 'XYZ', 15, 25, 77),('2014-05-17', 'DEF', 12, 40, 50)
) as t(Datefiled, Field1, Field2, Field3, Field4)
), cte AS (
SELECT CAST(MIN(Datefiled) AS DATE) as date_,
CAST(MAX(Datefiled) AS DATE) AS maxd
FROM datat
UNION ALL
SELECT DATEADD(day,1,date_), maxd
FROM cte
WHERE date_ < maxd
)
SELECT CAST([Month] as nvarchar(2)) + '/' + CAST([Year] as nvarchar(4)) as [Month/Year],
Field1,
Field2,
Field3,
Field4
FROM (
SELECT DISTINCT
MONTH(date_) as [Month],
YEAR(date_) as [Year],
Field1,
Field2,
Field3,
Field4
FROM cte c
LEFT JOIN (
SELECT TOP 1 WITH TIES CAST(DATEADD(MONTH, DATEDIFF(MONTH, 0, d1.Datefiled ), 0) as date) as [DateStart],
CAST(DATEADD(MILLISECOND, -3, DATEADD(MONTH, DATEDIFF(MONTH, 0, d2.Datefiled), 0)) as date) as [DateEnd],
d1.Field1,
d1.Field2,
d1.Field3,
d1.Field4
FROM datat d1
LEFT JOIN datat d2
ON d1.Datefiled < d2.Datefiled
ORDER BY ROW_NUMBER() OVER (PARTITION BY d1.Datefiled ORDER BY d2.Datefiled)
) as d
ON c.date_ between d.[DateStart] and ISNULL(d.[DateEnd],c.date_)
WHERE Field1 IS NOT NULL
) as t
ORDER BY [Year], [Month]
OPTION (MAXRECURSION 0)
Output:
Month/Year Field1 Field2 Field3 Field4
---------- ------ ----------- ----------- -----------
1/2012 ABC 10 15 17
2/2012 ABC 10 15 17
3/2012 ABC 10 15 17
4/2012 ABC 10 15 17
5/2012 ABC 10 15 17
6/2012 ABC 10 15 17
7/2012 ABC 10 15 17
8/2012 ABC 10 15 17
9/2012 ABC 10 15 17
10/2012 ABC 10 15 17
11/2012 ABC 10 15 17
12/2012 LKJ 16 12 13
1/2013 CVB 16 11 19
2/2013 CVB 16 11 19
3/2013 CVB 16 11 19
4/2013 PQR 7 80 65
5/2013 PQR 7 80 65
6/2013 PQR 7 80 65
7/2013 PQR 7 80 65
8/2013 PQR 7 80 65
9/2013 PQR 7 80 65
10/2013 PQR 7 80 65
11/2013 PQR 7 80 65
12/2013 PQR 7 80 65
1/2014 PQR 7 80 65
2/2014 PQR 7 80 65
3/2014 PQR 7 80 65
4/2014 XYZ 15 25 77
5/2014 DEF 12 40 50
(29 row(s) affected)

How do I get a total from a SQL query with a caculated field

I have a table that lists visits to a clinic. I'd like to get a "histogram" of sorts showing how frequently patients visit the clinic along with totals. Here's some sample code (tested under MS SQL Server 2005) to show what I'm talking about:
CREATE TABLE #test (
visit_id int IDENTITY(1,1),
patient_id int
);
DECLARE #num_patients int;
SELECT #num_patients = 1000 + ABS(CHECKSUM(NEWID())) % 250;
INSERT INTO #test (patient_id)
SELECT TOP 15 PERCENT ABS(CHECKSUM(NEWID())) % #num_patients
FROM sysobjects a, sysobjects b;
-- SELECT COUNT(*) AS total_visits FROM #test;
-- SELECT COUNT(DISTINCT patient_id) AS distinct_patients FROM #test;
SELECT CASE GROUPING(num_pat_visits) WHEN 1 THEN 'Total'
ELSE CAST(num_pat_visits AS varchar(5)) END AS num_pat_visits,
COUNT(*) AS num_patients, num_pat_visits * COUNT(*) AS tot_pat_visit
FROM
(SELECT patient_id, COUNT(*) AS num_pat_visits FROM #test GROUP BY patient_id) a
GROUP BY num_pat_visits WITH ROLLUP
ORDER BY CAST(num_pat_visits AS int) DESC;
This gets me almost to where I want:
num_pat_visits num_patients tot_pat_visit
-------------- ------------ -------------
60 1 60
54 2 108
52 2 104
51 4 204
50 3 150
49 3 147
48 7 336
47 7 329
46 15 690
45 15 675
44 29 1276
43 36 1548
42 45 1890
41 45 1845
40 59 2360
39 71 2769
38 51 1938
37 72 2664
36 77 2772
35 74 2590
34 72 2448
33 82 2706
32 90 2880
31 74 2294
30 69 2070
29 47 1363
28 30 840
27 27 729
26 26 676
25 21 525
24 13 312
23 4 92
22 5 110
21 4 84
20 2 40
18 2 36
Total 1186 NULL
However, I can't seem to get SQL Server to display the total number of visits where it says NULL on the total row.
Any ideas?
I think you can just do:
sum(num_pat_visits) as tot_pat_visit
SELECT CASE GROUPING(num_pat_visits) WHEN 1 THEN 'Total'
ELSE CAST(num_pat_visits AS varchar(5)) END AS num_pat_visits,
COUNT(*) AS num_patients,
--num_pat_visits * COUNT(*) AS tot_pat_visit
sum(num_pat_visits) as tot_pat_visit
FROM
(SELECT patient_id, COUNT(*) AS num_pat_visits FROM #test GROUP BY patient_id) a
GROUP BY num_pat_visits WITH ROLLUP
ORDER BY CAST(num_pat_visits AS int) DESC;

Resources