How to horizontally insert data into a table from another table where this data is positioned vertically? - pivot-table

I currently have a data in a table positioned vertically:
FILE ID: 001
RECORD 1 1111
RECORD 2 123456789012345
RECORD 3 A01 11
RECORD 4 A02 11
RECORD 5 A03 11
RECORD 6 0103050
RECORD 7 777
RECORD 8 A01 1
RECORD 9 A02 1
RECORD 10 A03 1111
RECORD 11 A04 11111
FILE ID: 002
RECORD 1 2222
RECORD 2 1234567
RECORD 3 A01 11
RECORD 4 A02 11
RECORD 5 A03 11
RECORD 6 0103050
RECORD 7 777
RECORD 8 A01 1
RECORD 9 A02 1
RECORD 10 A03 1111
RECORD 11 A04 11111
FILE ID: 003
RECORD 1 3333
RECORD 2 1234567
RECORD 3 A01 11
RECORD 4 A02 11
RECORD 5 A03 11
RECORD 6 0103050
RECORD 7 777
RECORD 8 A01 1
RECORD 9 A02 1
RECORD 10 A03 1111
RECORD 11 A04 11111
How can I insert it into another table so it is positioned horizontally, the following way:
FileID|Record1|Record2|Record3|Record4|Record5|Record6|Record7|Record8|Record9|Record10|Record11
--------------------------------------------------------------------------------------------------
001 |1111 |1111111|A01 11|A02 11|A03 11|0103050|777 |A01 1|A02 1|A03 1111|A04 11111
002 |2222 |1234567|A01 11|A02 11|A03 11|0103050|777 |A01 1|A02 1|A03 1111|A04 11111
003 |3333 |1234567|A01 11|A02 11|A03 11|0103050|777 |A01 1|A02 1|A03 1111|A04 11111
Thank's

I'm a little late to the party, but I'll give it a shot. This will only work if your data is consistent with file id followed by 11 records. First, you need to have a table with an identity column. I would make it a habit to do so when creating tables. Do your bulk insert into the following table. This will store your data with row id's which will be important later.
CREATE TABLE [dbo].[Table_1](
[TableId] [bigint] IDENTITY(1,1) NOT NULL,
[Column1] [varchar](255) NULL,
[Column2] [varchar](255) NULL
) ON [PRIMARY]
GO
Create this table for the pivoted data.
CREATE TABLE [dbo].[Table_2](
[Table2ID] [bigint] IDENTITY(1,1) NOT NULL,
[FileID] [varchar](255) NULL,
[Record1] [varchar](255) NULL,
[Record2] [varchar](255) NULL,
[Record3] [varchar](255) NULL,
[Record4] [varchar](255) NULL,
[Record5] [varchar](255) NULL,
[Record6] [varchar](255) NULL,
[Record7] [varchar](255) NULL,
[Record8] [varchar](255) NULL,
[Record9] [varchar](255) NULL,
[Record10] [varchar](255) NULL,
[Record11] [varchar](255) NULL
) ON [PRIMARY]
GO
Now to get the data from table 1 to table 2. I will use a Common Table Expression (CTE) and the LEAD function.
WITH preselect AS
(
SELECT Column1
,Column2 AS 'FileID'
,LEAD(Column2,1,0) OVER(ORDER BY TableId) AS 'Record1'
,LEAD(Column2,2,0) OVER(ORDER BY TableId) AS 'Record2'
,LEAD(Column2,3,0) OVER(ORDER BY TableId) AS 'Record3'
,LEAD(Column2,4,0) OVER(ORDER BY TableId) AS 'Record4'
,LEAD(Column2,5,0) OVER(ORDER BY TableId) AS 'Record5'
,LEAD(Column2,6,0) OVER(ORDER BY TableId) AS 'Record6'
,LEAD(Column2,7,0) OVER(ORDER BY TableId) AS 'Record7'
,LEAD(Column2,8,0) OVER(ORDER BY TableId) AS 'Record8'
,LEAD(Column2,9,0) OVER(ORDER BY TableId) AS 'Record9'
,LEAD(Column2,10,0) OVER(ORDER BY TableId) AS 'Record10'
,LEAD(Column2,11,0) OVER(ORDER BY TableId) AS 'Record11'
FROM Table_1
)
INSERT INTO Table_2
SELECT FileID,Record1,Record2,Record3,Record4,Record5,Record6,Record7
,Record8,Record9,Record10,Record11
FROM preselect
WHERE Column1 = 'FILE ID:'
I am ordering by the TableId in the LEAD function to ensure the order of the data. Then it is just a matter of getting the FileId value along with the values of the next 11 rows.
LEAD (Transact-SQL
Common Table Expression (CTE)

Related

JSON Many to Many RelationShip Group By

I'm trying to create an SQL query allowing me to do this:
I have 3 tables in SQL Server 2017:
CREATE TABLE [dbo].[PRODUCTCATEGORY]
(
[PROD_ID] [int] NOT NULL,
[CAT_ID] [int] NOT NULL
CONSTRAINT [PK_PRODUCTCATEGORY]
PRIMARY KEY CLUSTERED ([PROD_ID] ASC, [CAT_ID] ASC)
)
CREATE TABLE [dbo].[CATEGORY]
(
[CAT_ID] [int] IDENTITY(1,1) NOT NULL,
[CAT_TITLE] [varchar](50) NOT NULL
CONSTRAINT [PK_CATEGORY]
PRIMARY KEY CLUSTERED ([CAT_ID] ASC)
)
CREATE TABLE [dbo].[PRODUCT]
(
[PROD_ID] [int] IDENTITY(1,1) NOT NULL,
[PROD_TITLE] [varchar](50) NOT NULL
CONSTRAINT [PK_PRODUCT]
PRIMARY KEY CLUSTERED ([PROD_ID] ASC)
)
A product can have 1 to many categories
A category can have 1 to many products
PROD_ID
PROD_TITLE
1
Book 1
2
Book 2
CAT_ID
CAT_TITLE
1
Cat 1
2
Cat 2
3
Cat 3
PROD_ID
CAT_ID
1
1
1
2
2
1
2
3
I would like to retrieve this:
| CAT_ID |CAT_TITLE | PRODUCTS |
|:------- |:--------:|:------------------------------------------------------------------------|
| 1 | Cat 1 |[{"PROD_ID":1,"PROD_TITLE":"Book 1"},{"PROD_ID":2,"PROD_TITLE":"Book 2"}]|
| 2 | Cat 2 |[{"PROD_ID":1,"PROD_TITLE":"Book 1"}] |
| 3 | Cat 3 |[{"PROD_ID":2,"PROD_TITLE":"Book 2"}] |
Thanks for your help
I just found this, using FOR JSON:
https://learn.microsoft.com/en-us/sql/relational-databases/json/format-query-results-as-json-with-for-json-sql-server?view=sql-server-ver15
I think something like this might work:
SELECT c.CAT_ID, c.CAT_TITLE,
(
SELECT p.PROD_ID, p.PROD_TITLE
FROM PRODUCT p
JOIN PRODUCTCATEGORY pc ON pc.PROD_ID = p.PROD_ID
WHERE pc.CAT_ID = c.CAT_ID
FOR JSON PATH
) AS ProductsAsJson
FROM CATEGORY c

Finding missing records in joined tables using ID and Dates in SQL?

I'm having trouble writing a check that will find missing records.
My tables are Provider, ProviderRelationship, Agreement, and AgreementProvider. I need to find missing records where the Provider has a ProviderRelationship, but no record for AgreementProvider for that specific time frame.
Both ProviderRelationship and AgreementProvider have StartDate and EndDate fields. Providers can only have 1 current ProviderRelationship, but they can have multiple ProviderRelationship entries. For example, ProviderA has ProviderRelationship1 on 3/17/2019, then ProviderRelationship2 from 3/18/2019 to 6/30/2020 and AgreementProvider2 for the same dates.
The closest I've come is this, which gets Providers that have never had any AgreementProvider entries at all. When I add in the date validation, it also includes the previous ProviderRelationships.
CREATE TABLE dbo.Provider
ProviderID INT IDENTITY(1,1) NOT NULL,
Name VARCHAR(200) NULL
ProviderID Name
9003055 ABC
6102 DEF
2743 Desired
9999 Ideal
CREATE TABLE dbo.ProviderRelationship
ProviderRelationshipID INT IDENTITY(1,1) NOT NULL,
ParentProviderID INT NOT NULL,
ProviderID INT NOT NULL,
StartDate DATE NOT NULL,
EndDate DATE NOT NULL
ProviderRelationshipID ParentProviderID ProviderID StartDate EndDate
1 9003055 9003055 2017-03-01 2017-03-27 --providers who are the parent provider should not appear
2 1021 9003055 2017-03-27 2017-03-27
3 1021 9003055 2017-03-28 2100-01-01 --should not appear
4 184 6102 2015-07-01 2015-07-01
5 6102 6102 2015-07-02 2100-01-01
6 244 2743 2015-07-01 2100-01-01 --there is no AgreementProviderID record for this one
7 1234 9999 2018-08-01 2019-09-01
8 4321 9999 2019-10-01 2100-01-01 --this is the ideal result, since there is a gap in AgreementProvider records
CREATE TABLE dbo.Agreement
AgreementID INT IDENTITY(1,1) NOT NULL
ProviderID INT NULL, --this is the ParentProviderID
RefRegionID INT NULL
AgreementID ProviderID
1 1021
2 1021
3 184
4 184
5 184
6 184
7 244
8 244
9 244
10 1234
11 4321
CREATE TABLE dbo.AgreementProvider
AgreementProviderID INT IDENTITY(1,1) NOT NULL
AgreementID INT NULL,
ProviderID INT NULL,
StartDate DATE NULL,
EndDate DATE NULL
AgreementProviderID AgreementID ProviderID StartDate EndDate
1 1 9003055 2017-03-28 2020-06-30
2 2 9003055 2017-03-28 2020-06-30
3 10 1234 2018-08-01 2020-06-30
SELECT DISTINCT o.*
FROM Provider p
JOIN dbo.ProviderRelationship prel ON prel.ProviderID = p.ProviderID
JOIN dbo.Agreement a ON a.ProviderID = prel.ParentProviderId
JOIN dbo.AgreementProvider ap ON ap.AgreementID = a.AgreementID
WHERE prel.ProviderID <> prel.ParentProviderId
AND p.ProviderID NOT IN (SELECT ap2.ProviderID FROM dbo.AgreementProvider ap2
JOIN dbo.ProviderRelationship prel2 ON prel2.ProviderID = ap2.ProviderID
WHERE prel.ParentProviderId = prel2.ParentProviderId)
It should not compare the date to a previous date, so ProviderID 9003055 should not appear. It should also not consider ProviderID when the ParentProviderID matches. It should get both Desired and Ideal ProviderIDs: Desired does not have a record, and Ideal does not have a current record for the current ProviderRelationship.
How would I rewrite this to include the specific time frame for each ProviderRelationship compared to the AgreementProvider information for those dates?
Ideal output would be this:
ProviderID ParentProviderID RelationshipStartDate RelationshipEndDate
2743 244 2015-07-01 2100-01-01
9999 4321 2019-10-01 2100-01-01
Maybe it's already doing what I want, because there are invalid entries for the ProviderIDs that I don't want included. Maybe this is good enough, I will have to confirm.

Generate an excel like report from SQL

I am novice to SQL and
I have two tables Ticket and TicketAttributes with following Schema
CREATE TABLE [dbo].[Ticket](
[TicketID] [int] IDENTITY(1,1) NOT NULL, --Primary key
[Category] [varchar](256) NOT NULL,
[Description] [varchar](256) NULL,
[LibID] [int] NOT NULL,
[Status] [smallint] NULL,
[LogID] [int] NULL)
Ticket Attributes
CREATE TABLE [dbo].[TicketAttributes](
[TicketID] [int] NOT NULL,
[TicketAttrID] [int] IDENTITY(1,1) NOT NULL,
[AttributeID] [int] NOT NULL,
[AttributeGroup] [varchar](255) NULL,
[AttributeValue] [nvarchar](max) NULL,
[Status] [smallint] NULL,
[LogID] [int] NULL)
Where Ticket Attribute is another table that stores different attributes of a ticket like TicketStatus, TicketCategory etc..
Now I need to generate a report that looks like
TicketStatus1 TicketStatus 2 TicketStatus3
-----------------------------------------------------------------
TicketCategory1 7 3
Ticketcategory2 4
TicketCategory3 8
I want to see the count of each of the status of each ticket category.
For Eg:-
I have the following Data in TicketTable
----------------------------------------------
TicketID Name Price Date
------------------------------------------------
155 Ticket4 $20 16 Jan 2016
157 Ticket3 $300 17 Jan 2016
158 Ticket1 $100 18 Jan 2016
159 Ticket2 $500 19 Jan 2016
Now in the TicketAttribute Table
----------------------------------------------
TicketID AttributeID AttributeValue
------------------------------------------------
155 500 Joe
155 600 Reserved
155 700 Economy
155 800 San Jose
where AttributeIDs
500=Nameofthe Passenger
600= Status of Ticket
700= Class
800= Destination
Now lets say I want to see what is the count of number of active tickets in each of the class per status
Booked Cancelled PaymentPending ............
-----------------------------------------------------------------
Economy 7 3
Economy Plus 4
Business 8
Hope I am clear now.
how to go about this using SQL Query
USING PIVOT
;WITH cte AS (
SELECT
c.AttributeValue as Class
,s.AttributeValue as StatusOfTicket
FROM
Ticket t
LEFT JOIN TicketAttributes c
ON t.TicketId = c.TicketId
AND c.AttributeID = 700
LEFT JOIN TicketAttributes s
ON t.TicketId = s.TicketId
AND s.AttributeID = 600
)
SELECT *
FROM
cte
PIVOT (
COUNT(StatusOfTicket) FOR StatusOfTicket IN (Reserved,Cancelled,PaymentPending)
) p
USING Conditional Aggregation:
SELECT
c.AttributeValue as Class
,COUNT(DISTINCT CASE WHEN s.AttributeValue = 'Reserved' THEN c.TicketId END) as Reserved
,COUNT(DISTINCT CASE WHEN s.AttributeValue = 'Cancelled' THEN c.TicketId END) as Cancelled
,COUNT(DISTINCT CASE WHEN s.AttributeValue = 'PaymentPending' THEN c.TicketId END) as PaymentPending
FROM
Ticket t
LEFT JOIN TicketAttributes c
ON t.TicketId = c.TicketId
AND c.AttributeID = 700
LEFT JOIN TicketAttributes s
ON t.TicketId = s.TicketId
AND s.AttributeID = 600
GROUP BY
c.AttributeValue

SQL where clause for self-referencing table

I have something like the following table:
CREATE TABLE [dbo].[Test]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](450) NULL,
[Description] [nvarchar](4000) NULL,
[Created] [datetime] NULL,
[OrgId] [int] NULL CONSTRAINT [FK_Test_OrgId] FOREIGN KEY REFERENCES Test(Id),
CONSTRAINT [PK_Test]
PRIMARY KEY CLUSTERED ([Id] ASC)
)
A new entry has OrgId = null. If an entry has been edited, a new row is created with OrgId set to its original parent. If an entry is edited multiple times, all children will have OrgId set to the Id of the original row. The created datetime provides the "order".
What I need to do is select only the newest versions.
Given the table below, I am looking to select only Id 3, 5 & 6
Id Title Description Created PreId
-----------------------------------------------------
1 Car Orginal car 2014-01-01 NULL
2 House Original house 2014-01-01 NULL
3 Bike Original bike 2014-01-01 NULL
4 Car Car updated 2014-06-01 1
5 Car Car updated again 2014-08-01 1
6 House house updated 2014-09-01 2
Any input appreciated.
Thanks.
Since all records are pointing at the original row (and not the previous one) :
SELECT ID, Title, DEscription, CREATED, PreID
FROM
(SELECT ID, Title, DEscription, CREATED, PreID,
ROW_NUMBER() over(partition by ISNULL(OrgID,id) order by id desc) rn
FROM test) A
where RN = 1
WITH Titles AS
(
SELECT DISTINCT Title
FROM dbo.Test
)
SELECT A.ID, Ti.Title, A.[Description], A.Created, A.OrgId
FROM Titles AS Ti
OUTER APPLY (SELECT TOP (1) ID, [Description], [Created], [OrgId]
FROM dbo.Test AS Te
WHERE Te.Title = Ti.Title
ORDER BY Created DESC
) AS A;

SQL Server join query not retrieving proper result

Select the list of all dealers whose vehicles are never assigned to any customer i.e that vehicle is not present in PS3_VehicleBooking, and committed date is greater than today's date.
3 tables to be used are-
CREATE TABLE PS3_Dealer(
ID int IDENTITY(1,1) NOT NULL Primary KEY,
DealerID varchar(255) NULL,
DealerName varchar(255) NOT NULL,
ContactNo varchar(255) NOT NULL,
NoOfVehicles bigint NOT NULL,
CommittedDate date NOT NULL
);
create table PS3_Vehicle
(
ID int IDENTITY(1,1) NOT NULL Primary Key,
DealerID varchar(255) NOT NULL,
VehicleID varchar(255) UNIQUE NOT NULL,
VehicleName varchar(255) NOT NULL,
Capacity BIGINT NOT NULL
);
create table PS3_VehicleBooking
(
ID int IDENTITY(1,1) NOT NULL Primary Key,
BookingID varchar(255) NOT NULL UNIQUE,
VehicleID varchar(255) NOT NULL,
StartDate date NOT NULL,
EndDate date NOT NULL
);
PS3_Dealer values-
DealerID DealerName ContactNo NoOfVehicles CommittedDate
1 ng 9 5 2013-12-12
2 nikki 5 7 2013-12-25
3 nik 4 6 2013-10-11
4 hj 2 2 2014-11-10
5 pk 67 8 2013-10-10
PS3_Vehicle
DealerID VehicleID VehicleName Capacity
1 V1 ind 4
2 V2 innova 5
3 V3 innova 6
1 V4 ula 8
4 V5 hkk 2
5 V6 ghi 9
2 V7 bjhgi 4
PS3_VehicleBooking-
BookingID VehicleID StartDate EndDate
1 V1 2013-12-13 2013-12-17
2 V2 2013-10-11 2013-10-13
3 V3 2014-12-10 2014-12-13
4 V4 2012-10-10 2012-10-13
5 V2 2013-12-14 2013-12-18
expected outcome-
DealerID DealerName ContactNo NoOfVehicles CommittedDate
4 hj 2 2 2014-11-10
but i am getting-
DealerID DealerName ContactNo NoOfVehicles CommittedDate
4 hj 2 2 2014-11-10
2 Nikki 5 7 2013-12-25
i dont want dealer id 2 in result because V2 provided by dealer id 2 is present in PS3_Booking.
My query is-
SELECT h.DealerID,
h.DealerName,
h.ContactNo,
h.NoOfVehicles,
h.CommittedDate
FROM PS3_Dealer h
INNER JOIN(SELECT DealerID,
PS3_VehicleBooking.VehicleID
FROM PS3_Vehicle
LEFT JOIN PS3_VehicleBooking
ON PS3_Vehicle.VehicleID = PS3_VehicleBooking.VehicleID) w
ON h.DealerID = w.DealerID
WHERE w.VehicleID IS NULL
AND h.CommittedDate > GETDATE()
please correct where i am wrong?
The problem is that DealerID 2 has 2 Vehicles. One that has booking, and the other does not. When you run
SELECT DealerID,
PS3_VehicleBooking.VehicleID
FROM PS3_Vehicle
LEFT JOIN PS3_VehicleBooking
ON PS3_Vehicle.VehicleID = PS3_VehicleBooking.VehicleID
You will get one record that has DealerID 2 with NULL VehicleID and the other none NULL Vehicle ID.
You can try to the run the statement below to get the desired results (may not be the most optimal, but it is a fix to your statement):
SELECT h.DealerID,
h.DealerName,
h.ContactNo,
h.NoOfVehicles,
h.CommittedDate
FROM PS3_Dealer h
INNER JOIN(SELECT DealerID,
MAX(PS3_VehicleBooking.VehicleID) as VehicleID
FROM PS3_Vehicle
LEFT JOIN PS3_VehicleBooking
ON PS3_Vehicle.VehicleID = PS3_VehicleBooking.VehicleID
GROUP BY DealerID
) w
ON h.DealerID = w.DealerID
WHERE w.VehicleID IS NULL
AND h.CommittedDate > GETDATE()
Edited to actually answer the question
You were getting Nikki because there does exist a car for her (V7) that is not in the booking table.
This should exclude Nikki.
SELECT h.DealerID,
h.DealerName,
h.ContactNo,
h.NoOfVehicles,
h.CommittedDate
FROM PS3_Dealer d
WHERE NOT EXISTS
(SELECT *
FROM PS3_VehicleBookingb
JOIN PS3_Vehiclev ON b.vehicleID = v.VehicleID
JOIN PS3_Dealerd2 ON d2.dealerID = v.dealerID
WHERE d2.dealerID = d.dealerID)
AND CommittedDate > Current_date()
http://sqlfiddle.com/#!2/fb365/19

Resources