SQL Server Special display last row - sql

I have this database Student.
ID ( auto incremment) Nume Sum DataEnter
1 Alex 100 2013-05-20
2 Marian 200 2014-04-14
3 Vasile 150 2012-01-01
4 Andrei 100 2013-05-04
5 Teo 200 2013-02-11
I use this to display duplicate :
SELECT ID, Nume, Sum, DataEnter, FROM dbo.student
Where ISNULL(Sum, 0) IN (Select ISNULL (Sum,0) from dbo.student
group BY SUM
HAVING COUNT(*)>1 )
order by SUM desc, ID desc, DataEnter desc
Display this :
200 5 Teo 2013-02-11
200 2 Marian 2014-04-14
100 4 Andrei 2013-05-04
100 1 Alex 2013-05-20
Now : I enter a new data for example :
100 6 Costy with today dataenter day : 2014-05-27
Display this :
200 5 Teo 2013-02-11
200 2 Marian 2014-04-14
100 6 Costy 2014-05-27
100 4 Andrei 2013-05-04
100 1 Alex 2013-05-20
I want to display last duplicate category that enter sort by date. I want to display :
100 6 Costy 2014-05-27
100 4 Andrei 2013-05-04
100 1 Alex 2013-05-20
200 5 Teo 2013-02-11
200 2 Marian 2014-04-14
because 100 7 Costy 2014-05-27 is the last enter.

I hope this will help you.
Set Dateformat ymd
Declare #Student table
(ID int identity(1,1), Name varchar(20),[Sum] int,DataEnter Date)
Insert into #Student Values
('Alex' ,100,'2013-05-20'),
('Marian' ,200,'2014-04-14'),
('Vasile' ,150,'2012-01-01'),
('Andrei' ,100,'2013-05-04'),
('Teo' ,200,'2013-02-11')
Select A.Sum,A.ID,A.Name,A.DataEnter
From #Student A
Join (
Select Sum [Sum],max(DataEnter) DataEnter
from #Student
group By Sum
having Count(*) > 1) Lu
On A.Sum = Lu.Sum
order By Lu.DataEnter Desc,A.ID Desc
Result
Adding record
Insert into #Student Values
('Costy' ,100,'2014-05-27')
Select A.Sum,A.ID,A.Name,A.DataEnter
From #Student A
Join (
Select Sum [Sum],max(DataEnter) DataEnter
from #Student
group By Sum
having Count(*) > 1) Lu
On A.Sum = Lu.Sum
order By Lu.DataEnter Desc,A.ID Desc
Result
Adding 1 more record
Insert into #Student Values
('Mary' ,200,'2015-05-27')
Select A.Sum,A.ID,A.Name,A.DataEnter
From #Student A
Join (
Select Sum [Sum],max(DataEnter) DataEnter
from #Student
group By Sum
having Count(*) > 1) Lu
On A.Sum = Lu.Sum
order By Lu.DataEnter Desc,A.ID Desc
result.

Related

find previous value based on condition postgresql

id account amount
123 abc 10
1234 abc 12
4568 abc 16
456 def 20
458 def 30
i want to filter unique id whose difference(amount) is less than 5 (group by account). Here the answer is like:
id:
123
1234
4568
You could combine LEAD and LAG to get the desired result.
SELECT id
FROM (
SELECT t.*
,amount - LAG(amount, 1, 0) OVER (
PARTITION BY account ORDER BY amount
) AS diff1
,amount - LEAD(amount, 1, 0) OVER (
PARTITION BY account ORDER BY amount
) AS diff2
FROM t
) s
WHERE abs(diff1) < 5
OR abs(diff2) < 5;
Demo

Group by in PIVOT operator

How do i use the group by clause in the PIVOT operator?
I tried with the following code but i get the null values and the results are not getting aggregated.
select EmpName, CHN,HYD FROM location
PIVOT (Sum(salary) for EmpLoc in ([CHN], [HYD]))
AS
pivottable
I want the final output to be like this.
CHN HYD
kunder 400 200
shetty 150 150
or
CHN HYD Total
kunder 400 200 600
shetty 150 150 300
Total 550 350 900
Just add the derived column Total=CHN+HYD and a sub-query to create the Total Row
The Seq (though not displayed) will put the Total row at the bottom
Declare #YourTable table (EmpLoc varchar(25),EmpName varchar(25),Salary int)
Insert Into #YourTable values
('HYD','kunder',200)
,('HYD','shetty',150)
,('CHN','shetty',150)
,('CHN','kunder',200)
,('CHN','kunder',200)
Select EmpName, CHN,HYD,Total=CHN+HYD
From (
Select Seq=0,EmpLoc,EmpName,Salary From #YourTable
Union All
Select Seq=1,EmpLoc,'Total',Salary From #YourTable
) A
pivot (sum(Salary) for EmpLoc in ([CHN], [HYD])) P
Returns
EmpName CHN HYD Total
kunder 400 200 600
shetty 150 150 300
Total 550 350 900
Declare #YourTable table (EmpLoc varchar(25),EmpName varchar(25),Salary int)
Insert Into #YourTable values
('HYD','kunder',200)
,('HYD','shetty',150)
,('CHN','shetty',150)
,('CHN','kunder',200)
,('CHN','kunder',200)
;with cte as
(
SELECT * from
(
select * from #YourTable
) as y
pivot
(
sum(salary)
for EmpLoc in ([CHN], [HYD])
) as p
)
SELECT
EmpName,sum(CHN)CHN ,sum(HYD)HYD
FROM CTE
GROUP BY EmpName;
I have no issue using your code from your example to get your desired results. I am guessing that your query is not as simple as your example, and as such is introducing other complications not shown here.
You may need to use a subquery and pivot using just the columns necessary for the pivot and join back to the rest of your query to get the results you are looking for using pivot().
Using conditional aggregation may be a simpler solution:
select
empname
, CHN = sum(case when emploc = 'CHN' then salary else 0 end)
, HYD = sum(case when emploc = 'HYD' then salary else 0 end)
--, Total = sum(salary) /* Optional total */
from location
group by empname
rextester demo: http://rextester.com/LYRH81756
returns:
+---------+-----+-----+
| EmpName | CHN | HYD |
+---------+-----+-----+
| kunder | 400 | 200 |
| shetty | 150 | 150 |
+---------+-----+-----+

Sql Server group by sets of columns

I have a data set where I need to count patient visits with such rules:
Two or more visits to the same doctor in the same day count as 1 visit, regardless of the reason
Two or more visits to different doctors for the same reason count as 1 visit
Two or more visits to different doctors on the same day for different reasons count as two or more visits.
Example data:
DoctorId PatientId VisitDate ReasonCode RowId
-------- --------- --------- ---------- -----
1 100 2014-01-01 200 1
1 100 2014-01-01 210 2
2 100 2014-01-01 200 3
2 100 2014-01-11 300 4
1 100 2014-01-15 200 5
2 400 2014-01-15 200 6
In this example, my final count would be based on grouping rowId 1, 2, 3 for 1 visit; grouping row 4 as 1 visit, grouping row 5 as 1 visit for a total of 3 visits for patient 100. Patient 400 has 1 visit as well.
patientid visitdate numberofvisits
--------- --------- --------------
100 2014-01-01 3
100 2014-01-11 1
100 2014-01-15 1
400 2014-01-15 1
Where I'm stuck is how to handle the group by so that I get the different scenarios covered. If the grouping were doctor, date, I'd be fine. If it were doctor, date, ReasonCode, I'd be fine. It's the logic of the doctorId and the ReasonCode in the scenario where 2 doctors are involved, and doctorid and date in the other when it's the same doctor. I've not been deeply into Sql Server in a long time, so it's possible that a common table expression is the solution and I'm not seeing it. I'm using Sql Server 2014 and there's a decent lattitude in performance. I would be looking for a sql server query that produces the results above. As best I can tell, there's no way to group this the way I need it counted.
The answer was an except clause and grouping each of the sets before a final count. Sometimes, we over-complicate things.
DECLARE #tblAllData TABLE
(
DoctorId INT NOT NULL
, PatientId INT NOT NULL
, VisitDate DATE NOT NULL
, ReasonCode INT NOT NULL
, RowId INT NOT NULL
)
INSERT #tblAllData
SELECT
1,100,'2014-01-01',200,1
UNION ALL
SELECT
1,100,'2014-01-01',210,2
UNION ALL
SELECT
2,100,'2014-01-01',200,3
UNION ALL
SELECT
2,100,'2014-01-11',300,4
UNION ALL
SELECT
1,100,'2014-01-15',200,5
UNION ALL
SELECT
2,400,'2014-01-15',200,6
DECLARE #tblTempCountedRows AS TABLE
(
PatientId INT NOT NULL
, VisitDate DATE
, ReasonCode INT
)
INSERT #tblTempCountedRows
SELECT PatientId, VisitDate,0
FROM #tblAllData
GROUP BY PatientId, DoctorId, VisitDate
EXCEPT
SELECT PatientId, VisitDate, ReasonCode
FROM #tblAllData
GROUP BY PatientId, VisitDate, ReasonCode
select * from #tblTempCountedRows
DECLARE #tblFinalCountedRows AS TABLE
(
PatientId INT NOT NULL
, VisitCount INT
)
INSERT #tblFinalCountedRows
SELECT
PatientId
, count(1) as Member_visit_Count
FROM
#tblTempCountedRows
GROUP BY PatientId
SELECT * from #tblFinalCountedRows
Here's a Sql Fiddle with the results:
Sql Fiddle

SQL query to group by data but with order by clause

I have table booking in which I have data
GUEST_NO HOTEL_NO DATE_FROM DATE_TO ROOM_NO
1 1 2015-05-07 2015-05-08 103
1 1 2015-05-11 2015-05-12 104
1 1 2015-05-14 2015-05-15 103
1 1 2015-05-17 2015-05-20 101
2 2 2015-05-01 2015-05-02 204
2 2 2015-05-04 2015-05-05 203
2 2 2015-05-17 2015-05-22 202
What I want is to get the result as.
1 ) It should show output as Guest_no, Hotel_no, Room_no, and column with count as number of time previous three column combination repeated.
So OutPut should like
GUEST_NO HOTEL_NO ROOM_NO Count
1 1 103 2
1 1 104 1
1 1 101 1
2 2 204 1
etc. But I want result to in ordered way e.g.: The output should be order by bk.date_to desc
My query is as below its showing me count but if I use order by its not working
select bk.guest_no, bk.hotel_no, bk.room_no,
count(bk.guest_no+bk.hotel_no+bk.room_no) as noOfTimesRoomBooked
from booking bk
group by bk.guest_no, bk.hotel_no, bk.room_no, bk.date_to
order by bk.date_to desc
So with adding order by result is showing different , because as I added order by date_to column so i have to add this column is group by clause too which will end up in different result as below
GUEST_NO HOTEL_NO ROOM_NO Count
1 1 103 1
1 1 104 1
1 1 103 1
1 1 101 1
2 2 204 1
Which is not the output I want.
I want these four column but with order by desc of date_to column and count as no of repetition of first 3 columns
I think a good way to do this would be grouping by guest_no, hotel_no and room_no, and sorting by the maximum (i.e. most recent) booking date in each group.
SELECT
guest_no,
hotel_no,
room_no,
COUNT(1) AS BookingCount
FROM
booking
GROUP BY
guest_no,
hotel_no,
room_no
ORDER BY
MAX(date_to) DESC;
Maybe this is what you're looking for?
select
guest_no,
hotel_no,
room_no,
count(*) as Count
from
booking
group by
guest_no,
hotel_no,
room_no
order by
min(date_to) desc
Or maybe max() instead of min(). SQL Fiddle: http://sqlfiddle.com/#!6/e684c/3
You could try this.
select t.* from
(
select bk.guest_no, bk.hotel_no, bk.room_no, bk.date_to,
count(*) as noOfTimesBooked from booking bk
group by bk.guest_no, bk.hotel_no, bk.room_no, bk.date_to
) t
order by t.date_to
You will also have to select date_to and then group the result by it.
If you use 'group by' clause, SQL Server doesn't allow you to use 'order by'. So you can make a sub query and use 'order by' in the outer query.
SELECT * FROM
(select bk.guest_no,bk.hotel_no,bk.room_no
,count(bk.guest_no+bk.hotel_no+bk.room_no) as noOfTimesRoomBooked,
(SELECT MAX(date_to) FROM booking CK
WHERE CK.guest_no=BK.guest_no AND bk.hotel_no=CK.bk.hotel_no
bk.room_no=CK.ROOM_NO ) AS DATEBOOK
from booking bk
group by bk.guest_no,bk.hotel_no,bk.room_no,bk.date_to) A
ORDER BY DATEBOOK
IT MIGHT HELP YOU

How to select 6 top records of each individual records at the database when selecting from all rows

Assume that i have the following table
CREATE TABLE #tblUsersPokemons (
RecordId int NOT NULL,
PokemonId int NOT NULL,
PokemonExp int NOT NULL,
PokemonLevel int NOT NULL,
UserId int NOT NULL
)
Now the below query works awesome as expected
select
SUM(cast(PokemonExp as bigint)) as TotalExp,
MAX(PokemonLevel) as MaxPokeLevel,
Count(PokemonId) as TotalPoke,
UserId
from #tblUsersPokemons
group by UserId
Here example result of such query
ToplamExp MaxPokeLevel TotalPoke UserId
----------- --------------- ----------- --------
29372294 101 4 1
1134696 98 1 2
1400 98 1 101
24534365 98 4 102
1400 98 1 1102
1400 98 1 1103
1400 98 1 2102
1400 98 1 2103
789220 98 7 2105
1468 98 1 3104
Now here my question comes
I want to limit counted PokemonIds. What i mean is i want to select maximum 6 of each same PokemonId records. And from these records top 6 ordered desc by PokemonExp should be counted in.
For example a user has the below records
From this table the query should take record id : 1,2,3,4,5,6,9 and not take 7,8 since top 6 records for PokemonId 1 taken
If I understand correctly, you want the aggregations on the top 6 rows for each user. You can do this easily using row_number():
select SUM(cast(PokemonExp as bigint)) as ToplamExp,
MAX(PokemonLevel) as MaxPokeLevel,
Count(PokemonId) as TotalPoke,UserId
from (select p.*,
row_number() over (partition by userid order by pokemanexp desc) as seqnum
from tblUsersPokemons p
) p
where seqnum <= 6
group by UserId;
EDIT:
I think you want to include PokemonId in the partition by clause:
select SUM(cast(PokemonExp as bigint)) as ToplamExp,
MAX(PokemonLevel) as MaxPokeLevel,
Count(PokemonId) as TotalPoke,UserId
from (select p.*,
row_number() over (partition by userid, PokemonId
order by pokemanexp desc) as seqnum
from tblUsersPokemons p
) p
where seqnum <= 6
group by UserId;