Using Pivot or UnPivot to get Output Dynamically - sql

I have a table with the following structure that I want to receive output from this table dynamically. But I do not know how to use Pivot and UnPivot.
The list of fields I use is as follows.
SELECT [RoomID]
,[RoomNumber]
,[RoomType]
,[RoomTypeDescription]
,[RoomBed]
,[PriceOfPerNight]
,[RoomStatuse]
,[RoomStatuseDesc]
,[RoomFloorID]
,[RoomFloorTitle]
FROM [HotelOnline].[dbo].[XtblRooms]
RoomID RoomNumber RType RDesc Beds Price RoomStatuse RDesc FloorID RoomFloorTitle
1 RM100001 2 Degree 2 6 9000000.00 1 Free 1 Floor 001
2 RM100002 1 Degree 1 4 6000000.00 1 Free 1 Floor 001
3 RM100003 2 Degree 2 3 4500000.00 1 Free 1 Floor 001
4 RM100004 3 Degree 3 5 4800000.00 1 Free 1 Floor 001
5 RM100005 1 Degree 1 3 4700000.00 1 Free 1 Floor 001
6 RM100006 1 Degree 1 6 7500000.00 1 Free 1 Floor 001
7 RM100007 1 Degree 1 5 7000000.00 1 Free 1 Floor 001
8 RM100008 1 Degree 1 2 2500000.00 1 Free 1 Floor 001
9 RM100009 3 Degree 3 3 3500000.00 1 Free 1 Floor 001
10 RM100010 3 Degree 3 8 8000000.00 1 Free 1 Floor 001
11 RM100011 2 Degree 2 5 6500000.00 1 Free 2 Floor 002
12 RM100012 3 Degree 3 2 3800000.00 1 Free 2 Floor 002
13 RM100013 2 Degree 2 5 9650000.00 1 Free 2 Floor 002
14 RM100014 3 Degree 3 2 2500000.00 1 Free 2 Floor 002
15 RM100015 2 Degree 2 2 4500000.00 1 Free 2 Floor 002
16 RM100016 3 Degree 3 4 4000000.00 1 Free 2 Floor 002
17 RM100017 1 Degree 1 2 2500000.00 1 Free 2 Floor 002
18 RM100018 3 Degree 3 3 4500000.00 1 Free 2 Floor 002
19 RM100019 2 Degree 2 5 5000000.00 1 Free 2 Floor 002
20 RM100020 2 Degree 2 4 4500000.00 1 Free 2 Floor 002
21 RM100021 1 Degree 1 6 7500000.00 1 Free 3 Floor 003
22 RM100022 2 Degree 2 3 3000000.00 1 Free 3 Floor 003
23 RM100023 3 Degree 3 3 2500000.00 1 Free 3 Floor 003
24 RM100024 1 Degree 1 3 2500000.00 1 Free 3 Floor 003
25 RM100025 2 Degree 2 5 4800000.00 1 Free 3 Floor 003
26 RM100026 3 Degree 3 4 4000000.00 1 Free 3 Floor 003
27 RM100027 2 Degree 2 2 1800000.00 1 Free 3 Floor 003
28 RM100028 3 Degree 3 5 4700000.00 1 Free 3 Floor 003
29 RM100029 1 Degree 1 3 3500000.00 1 Free 3 Floor 003
30 RM100030 2 Degree 2 6 4600000.00 1 Free 3 Floor 003
31 RM100031 2 Degree 2 5 4500000.00 1 Free 4 Floor 004
32 RM100032 1 Degree 1 2 3500000.00 1 Free 4 Floor 004
33 RM100033 3 Degree 3 4 3700000.00 1 Free 4 Floor 004
34 RM100034 2 Degree 2 3 2800000.00 1 Free 4 Floor 004
35 RM100035 3 Degree 3 6 5500000.00 1 Free 4 Floor 004
36 RM100036 2 Degree 2 4 3700000.00 1 Free 4 Floor 004
37 RM100037 3 Degree 3 6 5800000.00 1 Free 4 Floor 004
38 RM100038 1 Degree 1 3 4000000.00 1 Free 4 Floor 004
39 RM100039 1 Degree 1 5 5500000.00 1 Free 4 Floor 004
40 RM100040 1 Degree 1 6 6500000.00 1 Free 4 Floor 004
41 RM100041 1 Degree 1 4 4500000.00 1 Free 5 Floor 005
42 RM100042 2 Degree 2 6 5500000.00 1 Free 5 Floor 005
43 RM100043 2 Degree 2 4 4000000.00 1 Free 5 Floor 005
44 RM100044 2 Degree 2 3 3500000.00 1 Free 5 Floor 005
45 RM100045 3 Degree 3 3 3000000.00 1 Free 5 Floor 005
46 RM100046 3 Degree 3 5 4000000.00 1 Free 5 Floor 005
47 RM100047 3 Degree 3 4 3900000.00 1 Free 5 Floor 005
48 RM100048 2 Degree 2 5 4700000.00 1 Free 5 Floor 005
49 RM100049 2 Degree 2 3 3800000.00 1 Free 5 Floor 005
50 RM100050 3 Degree 3 5 4700000.00 1 Free 5 Floor 005
This is the output I need.
Floor 001 Floor 002 Floor 003 Floor 004 Floor 005
==========================================================
RM100001 RM100012 RM100028 RM100033 RM100049
RM100002 RM100013 RM100029 RM100033 RM100050
.. . . . . .
I tried several ways but did not get the answer. Help if possible. I tried several ways but did not get the answer. Help if possible. If possible, use the dynamic method to get the answer. It does not matter if it is not for you. My problem will be solved in the same way as usual.

Because I am "illiterate" I was unable to answer this question:
--If you want a full working example for your data, provide full DDL and DML statements.
WITH YourTable AS(
SELECT *
FROM (VALUES
('1','RM100001','2','Degree 2','6','9000000.00','1','Free','1','Floor 001'),
('2','RM100002','1','Degree 1','4','6000000.00','1','Free','1','Floor 001'),
('3','RM100003','2','Degree 2','3','4500000.00','1','Free','1','Floor 001'),
('4','RM100004','3','Degree 3','5','4800000.00','1','Free','1','Floor 001'),
('5','RM100005','1','Degree 1','3','4700000.00','1','Free','1','Floor 001'),
('6','RM100006','1','Degree 1','6','7500000.00','1','Free','1','Floor 001'),
('7','RM100007','1','Degree 1','5','7000000.00','1','Free','1','Floor 001'),
('8','RM100008','1','Degree 1','2','2500000.00','1','Free','1','Floor 001'),
('9','RM100009','3','Degree 3','3','3500000.00','1','Free','1','Floor 001'),
('10','RM100010','3','Degree 3','8','8000000.00','1','Free','1','Floor 001'),
('11','RM100011','2','Degree 2','5','6500000.00','1','Free','2','Floor 002'))V(RoomID,RoomNumber,RType,RDesc,Beds,Price,RoomStatuse,RDesc2,FloorID,RoomFloorTitle)),
/*
Having multiple columns with the same name is a design flaw (not allowed).
I have named the second Rdesc as RDesc2, but this is also flawed (it breaks normalisation rules).
Fix your design, normalise your data.
*/
RNs AS(
SELECT RoomNumber,
RoomFloorTitle,
ROW_NUMBER() OVER (PARTITION BY RoomFloorTitle ORDER BY RoomNumber) AS RN --ORDER BY should be your ID/always ascending column
FROM YourTable)
SELECT MAX(CASE RoomFloorTitle WHEN 'Floor 001' THEN RoomNumber END) AS Floor001,
MAX(CASE RoomFloorTitle WHEN 'Floor 002' THEN RoomNumber END) AS Floor002
FROM RNs
GROUP BY RN;
db<>fiddle

SELECT *
FROM (
select RoomStatuseDesc,
RoomNumber,
count(*) over (partition by RoomStatuseDesc order by
RoomNumber) rm2 from XtblRooms)as XtblRooms
PIVOT (max(RoomNumber) --as R_count, min(RoomNumber) as r_start
for RoomStatuseDesc in('Floor1','Floor2', 'Floor3', 'Floor4', 'Floor5'))pvt

Related

Want to retreive data in required format from SQL SERVER table

I have a view as follows:
id paperid papercode papername marks1 marks2 total
1 1 001 paper-1 10 35 45
2 2 001 paper-2 12 40 52
3 3 002 paper-3 9 30 39
Now, I want data as below:
id paperid papercode papername marks1 marks2 total
1 1 001 001 22 75 97
3 3 002 paper-3 9 30 39
You can try below -
select min(id),min(paperid),papercode,min(papername),sum(marks1),sum(marks2),sum(marks3)
from tablename
group by papercode

Creating Pivots based for a rowcount in SQL

I have 2 tables T1 and T2.
T1 has the following columns:
Id, EntityId, TypeofValue, Year, value
EntityId can have 7 values:
1,2,3,4,5,100,101
Typeofvalue can have 2 values
1 indicates Actual
2 indicates Target
T2 has the following columns:
NoOfRecordsToDisplay
I need to fetch the number of records (if existing) for Target corresponding to an Id. The record count (1 if any record is present 0 if none) for Target needs to be grouped into two categories: First having Entityid 1 and Maximum records under Second group with entityids 2,3,4,100,101 [Not 5]
However, the catches are:
Sometimes Target value might not be present for a year
I need to get only last records for targets on the basis of NoOfRecordsToDisplay (The number of records to display comes from T2) for actual
Example1:
NoOfRecordsToDisplay =3, ID =123
The data below should return
CountGroup1: 1, Countgroup2: 1
as Entityid 1 has least one value for target for last 3 years -2015, 2014,2013 in this case
as Entityid 2 or 3 has at least 1 value for years -2015, 2014
Id EntityId TypeofValue Year Value
123 1 1 2015 55
123 1 1 2014 56
123 1 1 2013 57
123 1 1 2012 58
123 1 2 2015 50
123 1 2 2014 50
123 1 2 2013 50
123 1 2 2012 50
123 2 1 2015 55
123 2 1 2014 56
123 3 1 2015 57
123 3 1 2014 58
123 2 2 2015 55
123 2 2 2014 56
123 3 2 2015 57
124 1 1 2015 55
124 1 1 2014 56
124 2 1 2013 57
124 2 1 2012 58
124 1 2 2015 50
124 1 2 2014 50
124 2 2 2013 50
124 2 2 2012 50
Another dataset
NoOfRecordsToDisplay =3, ID =123
The data below should return:
CountGroup1: 0, Countgroup2: 1
as Entityid 1 has no target value for last 3 years (entityid 1 has a target value but for 2012)
as Entityid 2 has at one value for target years -2015 (entityid 3 has a target value but for 2010)
Id EntityId TypeofValue Year Value
123 1 1 2015 55
123 1 1 2014 56
123 1 1 2013 57
123 1 1 2012 58
123 1 2 2012 58
123 2 1 2015 55
123 2 1 2014 56
123 2 2 2015 55
123 2 2 2011 56
123 3 2 2010 57
Thank you so much for your help.
I have been trying to find this solution for a long time, I am not sure if Pivot will help
The question is different from the other one that I had posted as I am trying to create a group count based on entity groups.

3 Tables, JOIN query and alphabetic order

I am currently working with three tables where I am trying to figure out how to use a join to display once the title_id of any book with Dennis McCann as an editor. The tables have in common title_id and editor_id. Cant find a way to piece it all together. How to display once the title_id of any book with Dennis McCann as an editor?
SELECT * FROM title_editors;
EDITOR_ID TITLE_ EDITOR_ORDER
----------- ------ ------------
826-11-9034 Bu2075 2
826-11-9034 PS2091 2
826-11-9034 Ps2106 2
826-11-9034 PS3333 2
826-11-9034 PS7777 2
826-11-9034 pS1372 2
885-23-9140 MC2222 2
885-23-9140 MC3021 2
885-23-9140 Tc3281 2
885-23-9140 TC4203 2
885-23-9140 TC7777 2
321-55-8906 bU1032 2
321-55-8906 BU1111 2
321-55-8906 BU7832 2
321-55-8906 PC1035 2
321-55-8906 PC8888 2
321-55-8906 BU2075 3
777-02-9831 pc1035 3
777-02-9831 PC8888 3
943-88-7920 BU1032 1
943-88-7920 bu1111 1
943-88-7920 BU2075 1
943-88-7920 BU7832 1
943-88-7920 PC1035 1
943-88-7920 pc8888 1
993-86-0420 PS1372 1
993-86-0420 PS2091 1
993-86-0420 PS2106 1
993-86-0420 PS3333 1
993-86-0420 pS7777 1
993-86-0420 MC2222 1
993-86-0420 MC3021 1
993-86-0420 Tc3218 1
993-86-0420 TC4203 1
993-86-0420 TC7777 1
35 rows selected.
SQL> SELECT * FROM title_authors;
AUTHOR_ID TITLE_ AUTHOR_ORDER ROYALTY_SHARE
----------- ------ ------------ -------------
409-56-7008 Bu1032 1 .6
486-29-1786 PS7777 1 1
486-29-1786 pC9999 1 1
712-45-1867 MC2222 1 1
172-32-1176 Ps3333 1 1
213-46-8915 BU1032 2 .4
238-95-7766 PC1035 1 1
213-46-8915 Bu2075 1 1
998-72-3567 pS2091 1 .5
899-46-2035 PS2091 2 .5
998-72-3567 PS2106 1 1
722-51-5454 mc3021 1 .75
899-46-2035 MC3021 2 .25
807-91-6654 tC3218 1 1
274-80-9391 BU7832 1 1
427-17-2319 pC8888 1 .5
846-92-7186 PC8888 2 .5
756-30-7391 PS1372 1 .75
724-80-9391 PS1372 2 .25
724-80-9391 bu1111 1 .6
267-41-2394 bU1111 2 .4
672-71-3249 TC7777 1 .4
267-41-2394 TC7777 2 .3
472-27-2349 Tc7777 3 .3
648-92-1872 TC4203 1 1
25 rows selected.
SQL> SELECT * FROM editors;
EDITOR_ID EDITOR_LNAME EDITOR_FNAME EDITOR_POSITION PHONE ADDRESS CITY ST ZIP
----------- ----------------- ------------- --------------- ------------ -------------------- ------------ -- ------
321-55-8906 DeLongue Martinella Project 415 843-2222 3000 6th St. BERKELEY Ca 94710
723-48-9010 Sparks MANfred cOPY 303 721-3388 15 Sail DENVER Co 80237
777-02-9831 Samuelson Bernard proJect 415 843-6990 27 Yosemite OAKLAND Ca 94609
777-66-9902 Almond Alfred copy 312 699-4177 1010 E. DeVON CHICAGO Il 60018
826-11-9034 Himmel Eleanore pRoject 617 423-0552 97 Bleaker BOSTON Ma 02210
885-23-9140 Rutherford-Hayes Hannah PROJECT 301 468-3909 32 Rockbill Pike ROCKBILL MD 20852
993-86-0420 McCann Dennis acQuisition 301 468-3909 32 Rockbill Pike ROCKBill MD 20852
943-88-7920 Kaspchek Christof acquisitiOn 415 549-3909 18 Severe Rd. BERKELEY CA 94710
234-88-9720 Hunter Amanda acquisition 617 432-5586 18 Dowdy Ln. BOSTON MA 02210
You can try join on the table Editors and Ttile_Editors using the Editor_ID that will give you the matching records and you can filter out Only for the ' Dennis McCann ' using either multiple conditions in join or the where clause as,
WITHOUT WHERE
SELECT DISTINCT te.title_id,ed.EDITOR_ID,ed.EDITOR_LNAME,ed.EDITOR_FNAME
FROM
title_editors te JOIN editors ed
ON te.EDITOR_ID = ed.EDITOR_ID
AND ed.EDITOR_LNAME = 'McCann'
AND ed.EDITOR_FNAME = 'Dennis'
ORDER BY te.title_id
USing WHERE
SELECT DISTINCT te.title_id,ed.EDITOR_ID,ed.EDITOR_LNAME,ed.EDITOR_FNAME
FROM
title_editors te JOIN editors ed
ON te.EDITOR_ID = ed.EDITOR_ID
WHERE
ed.EDITOR_LNAME = 'McCann'
AND ed.EDITOR_FNAME = 'Dennis'
ORDER BY te.title_id
It would be easier with the in operator:
SELECT DISTINCT title_id
FROM title_editors
WHERE editor_id IN (SELECT editor_id
FROM editors
WHERE editor_fname = 'Dennis' AND
editor_lname = 'McCann')
ORDER BY title_id ASC

SQL : How to find number of occurrences without using HAVING or COUNT?

This is a trivial example, but I am trying to understand how to think creatively using SQL.
For example, I have the following tables below, and I want to query the names of folks who have three or more questions. How can I do this without using HAVING or COUNT? I wonder if this is possible using JOINS or something similar?
FOLKS
folkID name
---------- --------------
01 Bill
02 Joe
03 Amy
04 Mike
05 Chris
06 Elizabeth
07 James
08 Ashley
QUESTION
folkID questionRating questionDate
---------- ---------- ----------
01 2 2011-01-22
01 4 2011-01-27
02 4
03 2 2011-01-20
03 4 2011-01-12
03 2 2011-01-30
04 3 2011-01-09
05 3 2011-01-27
05 2 2011-01-22
05 4
06 3 2011-01-15
06 5 2011-01-19
07 5 2011-01-20
08 3 2011-01-02
Using SUM or CASE seems to be cheating to me!
I'm not sure if it's possible in your current formulation, but if you add a primary key to the question table (questionid) then the following seems to work:
SELECT DISTINCT Folks.folkid, Folks.name
FROM ((Folks
INNER JOIN Question AS Question_1 ON Folks.folkid = Question_1.folkid)
INNER JOIN Question AS Question_2 ON Folks.folkid = Question_2.folkid)
INNER JOIN Question AS Question_3 ON Folks.folkid = Question_3.folkid
WHERE (((Question_1.questionid) <> [Question_2].[questionid] And
(Question_1.questionid) <> [Question_3].[questionid]) AND
(Question_2.questionid) <> [Question_3].[questionid]);
Sorry, this is in MS Access SQL, but it should translate to any flavour of SQL.
Returns:
folkid name
3 Amy
5 Chris
Update: Just to explain why this works. Each join will return all the question ids asked by that person. The where clauses then leaves only unique rows of question ids. If there are less than three questions asked then there will be no unique rows.
For example, Bill:
folkid name Question_3.questionid Question_1.questionid Question_2.questionid
1 Bill 1 1 1
1 Bill 1 1 2
1 Bill 1 2 1
1 Bill 1 2 2
1 Bill 2 1 1
1 Bill 2 1 2
1 Bill 2 2 1
1 Bill 2 2 2
There are no rows where all the ids are different.
however for Amy:
folkid name Question_3.questionid Question_1.questionid Question_2.questionid
3 Amy 4 4 5
3 Amy 4 4 4
3 Amy 4 4 6
3 Amy 4 5 4
3 Amy 4 5 5
3 Amy 4 5 6
3 Amy 4 6 4
3 Amy 4 6 5
3 Amy 4 6 6
3 Amy 5 4 4
3 Amy 5 4 5
3 Amy 5 4 6
3 Amy 5 5 4
3 Amy 5 5 5
3 Amy 5 5 6
3 Amy 5 6 4
3 Amy 5 6 5
3 Amy 5 6 6
3 Amy 6 4 4
3 Amy 6 4 5
3 Amy 6 4 6
3 Amy 6 5 4
3 Amy 6 5 5
3 Amy 6 5 6
3 Amy 6 6 4
3 Amy 6 6 5
3 Amy 6 6 6
There are several rows which have different ids and hence these get returned by the above query.
you can try sum , to replace count.
SELECT SUM(CASE WHEN Field_name >=3 THEN field_name ELSE 0 END)
FROM tabel_name
SELECT f.*
FROM (
SELECT DISTINCT
COUNT(*) OVER (PARTITION BY folkID) AS [Count] --count questions for folks
,a.folkID
FROM QUESTION AS q
) AS p
INNER JOIN FOLKS as f ON f.folkID = q.folkID
WHERE p.[Count] > 3

SQL terminology to combine a NOT EXIST query with latest value

I am a beginner with basic knowledge.
I have a single table that I am trying to pull all UID's that have not had a particular code in the table within the past year.
My table looks like this: (but much larger of course)
FACID DPID EID DID UID DT Code Units Charge ET Ord
1 1 6 2 1002 15-Mar-07 99204 1 180 09:36.7 1
1 1 7 5 10004 15-Mar-07 99213 1 68 02:36.9 1
1 1 24 55 25887 15-Mar-07 99213 1 68 43:55.3 1
1 1 25 2 355688 15-Mar-07 99213 1 68 53:20.2 1
1 1 26 5 555654 15-Mar-07 99213 1 68 42:22.6 1
1 1 27 44 135514 15-Mar-07 99213 1 68 00:36.8 1
1 1 28 2 3244522 15-Mar-07 99214 1 98 34:59.4 1
1 1 29 5 235445 15-Mar-07 99213 1 68 56:42.1 1
1 1 30 3 3214444 15-Mar-07 99213 1 68 54:56.5 1
1 1 33 1 221444 15-Mar-07 99204 1 180 37:44.5 1
I am attempting to use the following, but this is not working for my time frame limits.
select distinct UID from PtProcTbl
where DT<'20120101'
and NOT EXISTS (Select Distinct UID
where Code in ('99203','99204','99205','99213',
'99214','99215','99244','99245'))
I need to know how to make sure the UID's that I am pulling are the ones don't have a DT after the 1/1/2012 cut off date that contains one of the NOT Exists codes.
The above query returned UID's that actually dates after 1/1/2012 that does contain one of the above codes...
Not sure what I am doing wrong or if I am totally off base on this..
Thanks in advance.
Are you sure you need the NOT EXISTS? How about instead:
AND Code NOT IN ('99203','99204','99205','99213','99214','99215','99244','99245')