I have a table like this.
+----+-------+---------+----------+---------+----------+---------+----------+
| id | Month | Debit_A | Credit_A | Debit_B | Credit_B | Debit_C | Credit_C |
+----+-------+---------+----------+---------+----------+---------+----------+
| 1 | Jan | 100.50 | | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 2 | Jan | | 100.50 | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 3 | Jan | 150.25 | | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 4 | Jan | | | | | 300.00 | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 5 | Jan | | | | | | 300.00 |
+----+-------+---------+----------+---------+----------+---------+----------+
| 6 | Feb | | | 79.80 | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 7 | Feb | | | | 79.80 | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 8 | Feb | | | 200.00 | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 9 | Feb | | | | 200.00 | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 10 | Mar | | | | | 1500.00 | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 11 | Mar | | | | | | 1500.00 |
+----+-------+---------+----------+---------+----------+---------+----------+
| 12 | Apr | 100.00 | | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 13 | Apr | | 50.00 | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 14 | May | | | 50.75 | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 15 | May | | | | 50.70 | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 16 | Jun | | | | | 75.50 | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 17 | Jun | | | | | | 75.50 |
+----+-------+---------+----------+---------+----------+---------+----------+
| 18 | Jun | | | | | 75.50 | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 19 | Jun | | | | | | 75.50 |
+----+-------+---------+----------+---------+----------+---------+----------+
| 20 | Jul | 89.50 | | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
What I want is combine the rows that have the same Month value and same Debit/Credit value to a new table. This will combine the Debit and Credit rows into one row.
Example:
+----+-------+---------+----------+---------+----------+---------+----------+
| id | Month | Debit_A | Credit_A | Debit_B | Credit_B | Debit_C | Credit_C |
+----+-------+---------+----------+---------+----------+---------+----------+
| 1 | Jan | 100.50 | 100.50 | | | 300.00 | 300.00 |
+----+-------+---------+----------+---------+----------+---------+----------+
| 2 | Jan | 150.25 | | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 3 | Feb | | | 79.80 | 79.80 | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 4 | Feb | | | 200.00 | 200.00 | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 5 | Mar | | | | | 1500.00 | 1500.00 |
+----+-------+---------+----------+---------+----------+---------+----------+
| 6 | Apr | 100.00 | | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 7 | Apr | | 50.00 | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 8 | May | | | 50.75 | 50.70 | | |
+----+-------+---------+----------+---------+----------+---------+----------+
| 9 | Jun | | | | | 75.50 | 75.50 |
+----+-------+---------+----------+---------+----------+---------+----------+
| 10 | Jun | | | | | 75.50 | 75.50 |
+----+-------+---------+----------+---------+----------+---------+----------+
| 11 | Jul | 89.50 | | | | | |
+----+-------+---------+----------+---------+----------+---------+----------+
How do I do this in SQL Server 2008 or SQL Server 2012?
-- 1st we import the raw account activity data
IF OBJECT_ID('dbo.RawActivity','U') IS NOT NULL
DROP TABLE dbo.RawActivity;
GO
-- for the sake of mnemonics--and precedence when ordering--transactions
-- for account A, B, C and so on are defined as 0 for debits and 1 for
-- credits, and month short names are replaced with their number
CREATE TABLE dbo.RawActivity(id int,
M int,
A0 money,
A1 money,
B0 money,
B1 money,
C0 money,
C1 money);
GO
INSERT dbo.RawActivity
VALUES
(1, 1, 100.50, NULL, NULL, NULL, NULL, NULL),
(2, 1, NULL, 100.50, NULL, NULL, NULL, NULL),
(3, 1, 150.25, NULL, NULL, NULL, NULL, NULL),
(4, 1, NULL, NULL, NULL, NULL, 300.00, NULL),
(5, 1, NULL, NULL, NULL, NULL, NULL, 300.00),
(6, 2, NULL, NULL, 79.80, NULL, NULL, NULL),
(7, 2, NULL, NULL, NULL, 79.80, NULL, NULL),
(8, 2, NULL, NULL, 200.00, NULL, NULL, NULL),
(9, 2, NULL, NULL, NULL, 200.00, NULL, NULL),
(10 ,3, NULL, NULL, NULL, NULL, 1500.00, NULL),
(11, 3, NULL, NULL, NULL, NULL, NULL, 1500.00),
(12, 4, 100.00, NULL, NULL, NULL, NULL, NULL),
(13, 4, NULL, 50.00, NULL, NULL, NULL, NULL),
(14, 5, NULL, NULL, 50.75, NULL, NULL, NULL),
(15, 5, NULL, NULL, NULL, 50.70, NULL, NULL),
(16, 6, NULL, NULL, NULL, NULL, 75.50, NULL),
(17, 6, NULL, NULL, NULL, NULL, NULL, 75.50),
(18, 6, NULL, NULL, NULL, NULL, 75.50, NULL),
(19, 6, NULL, NULL, NULL, NULL, NULL, 75.50),
(20, 7, 89.50, NULL, NULL, NULL, NULL, NULL);
GO
-- 2nd we are going to flatten the raw data into a spagetti of transactions
-- with type T and parent transaction
IF OBJECT_ID('dbo.Activity','U') IS NOT NULL
DROP TABLE dbo.Activity;
GO
CREATE TABLE dbo.Activity(id int, M int, amount money, T char(2), pid int);
GO
INSERT INTO dbo.Activity
SELECT id,
M,
-- amount: the 1st non null
ISNULL(A0, ISNULL(A1, ISNULL(B0, ISNULL(B1, ISNULL(C0, C1))))),
-- type
CASE
WHEN A0 IS NOT NULL THEN 'A0'
WHEN A1 IS NOT NULL THEN 'A1'
WHEN B0 IS NOT NULL THEN 'B0'
WHEN B1 IS NOT NULL THEN 'B1'
WHEN C0 IS NOT NULL THEN 'C0'
WHEN C1 IS NOT NULL THEN 'C1'
END,
-- parent id
NULL
FROM dbo.RawActivity;
-- 3rd it gets interesting; we update the parent id with the 1st transaction
-- of each month, with help from FIRST_VALUE...
UPDATE dbo.Activity SET pid = P.pid
FROM
(
SELECT P.id,
FIRST_VALUE(A.id) OVER(PARTITION BY A.M ORDER BY A.M, A.id) AS pid
FROM dbo.Activity AS P INNER JOIN
dbo.Activity AS A ON P.id = A.id
) AS P
WHERE dbo.Activity.id = P.id;
-- we update same month and type transactions parent so that they are not
-- added together...
UPDATE A
SET A.pid = A.id
FROM dbo.Activity AS A JOIN
dbo.Activity AS B ON A.pid = B.id AND A.T = B.T AND A.M = B.M;
-- and we look for (type, parent) duplicates to update the parent; this
-- catches subsequent transactions of the same type. The naming of
-- transaction types pays off here because of the partitioning, and
-- the new parent will be the transaction right above the duplicate
-- TODO: test with more than two consecutive transactions of the same
-- type (there is none in your data)
WITH Duplicates AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY T, pid ORDER BY id) AS r FROM dbo.Activity
)
UPDATE Duplicates SET pid = id - 1 WHERE r > 1;
-- finally, we can pivot the whole thing to get back to the desired output;
-- the outer SELECT statement is just for beautification.
SELECT ROW_NUMBER() OVER(ORDER BY M) AS id,
FORMAT(DATEFROMPARTS(YEAR(GETDATE()), M, 1), 'MMM') AS [Month],
A0 AS Debit_A,
A1 AS Credit_A,
B0 AS Debit_B,
B1 AS Credit_B,
C0 AS Debit_C,
C1 AS Credit_C
FROM
(
SELECT M,
SUM([A0]) AS A0,
SUM([A1]) AS A1,
SUM([B0]) AS B0,
SUM([B1]) AS B1,
SUM([C0]) AS C0,
SUM([C1]) AS C1
FROM
(
SELECT id, M, amount, T, pid FROM dbo.Activity
) AS A
PIVOT
(
SUM(amount)
FOR T IN ([A0], [A1], [B0], [B1], [C0], [C1])
) AS PVT
GROUP BY M, pid
) AS Result;
If I were you, I have two solutions for making this happen:
By using temp tables (Either physical table or temp tables {#Table or ##Table}) and making multiple updating the row for setting the values of those fields.
By using cursors (I usually don't prefer the cursors as it affects the performance of the database and to be honest, my skills with the cursors are really poor)
For the Temp tables
I would make an initial insert and setting the Debit values by 0 in the beggining
Make an update for each Debit Type
UPDATE:
SELECT id, Month, 0 AS Debit_A, 0 AS Credit_A, 0 AS Debit_B, 0 AS Credit_B, 0 AS Debit_C, 0 AS Credit_C
INTO #TempTable
FROM YourTable
GROUP BY Month
UPDATE T
SET Debit_A = Value
FROM #TempTable T
INNER JOIN DebitATable D
ON T.Month = D.Month
I'd use something like that (sorry as it is a little bit generic as I don't know the structure of the database)
You can use GROUP or SUM for the values you're getting in either the Debit or the Credit values
Shouldn't Jan be only one row then with Debit_A = 250.75?
In Standard SQL I guess you can use this, not sure if it fits with sql-server:
select sum(debit_a), sum(debit_b), .. from table name group by month;
Related
I'm using SQL Server 2017.
Table:
CREATE TABLE [T1]
(
REC_ID decimal(28,6) NOT NULL,
BUSINESS_NR decimal(10,6) NULL,
Description varchar(20) NULL,
);
INSERT INTO T1 (REC_ID,BUSINESS_NR, Description)
VALUES (312, 1, 'Created'),
(314, 1, 'Adjustment'),
(356, 2, 'Created'),
(388, 1, 'NoChange'),
(565, 2, 'Adjustment'),
(701, 2, 'NoChange'),
(769, 1, 'Adjustment'),
(832, 2, 'Adjustment'),
(992, 2, 'Closed'),
(995, 1, 'Closed');
Question:
I would like to give each 'Adjustment' a consecutive number per Business_NR.
Example
SELECT *
FROM T1 .......
ORDER BY Business_NR ASC, REC_ID ASC
Output:
+--------+-------------+-------------+-----------------+
| REC_ID | BUSINESS_NR | Description | Adjustment Count|
+--------+-------------+-------------+-----------------+
| 312 | 1 | Created | |
| 314 | 1 | Adjustment | 1 |
| 388 | 1 | NoChange | |
| 769 | 1 | Adjustment | 2 |
| 995 | 1 | Closed | |
| 356 | 2 | Created | |
| 565 | 2 | Adjustment | 1 |
| 701 | 2 | NoChange | |
| 832 | 2 | Adjustment | 2 |
| 992 | 2 | Closed | |
+--------+-------------+-------------+-----------------+
Info: the REC_ID is unique and consecutive for each table entry.
I have no useful attempt to show and therefore have not added any query samples.
SQL FIDDLE: LINK
Seems like you just want a ROW_NUMBER in a CASE expression:
CASE [Description] WHEN 'Adjustment' THEN ROW_NUMBER() OVER (PARTITION BY BUSINESS_NR, [Description] ORDER BY REC_ID ASC) END AS AdjustmentCount
I want to log any field changes in table Item to a log table called Events.
CREATE TABLE [dbo].[Items]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NULL,
[Description] [nvarchar](max) NULL,
[ParentId] [int] NULL,
[EntityStatusId] [int] NOT NULL,
[ItemTypeId] [int] NOT NULL,
[StartDate] [datetimeoffset](7) NULL,
[DueDate] [datetimeoffset](7) NULL,
[Budget] [decimal](18, 2) NULL,
[Cost] [decimal](18, 2) NULL,
[Progress] [int] NULL,
[StatusTypeId] [int] NULL,
[ImportanceTypeId] [int] NULL,
[PriorityTypeId] [int] NULL,
[CreatedDate] [datetimeoffset](7) NULL,
[HideChildren] [bit] NOT NULL,
[TenantId] [int] NOT NULL,
[OwnedBy] [int] NOT NULL,
[Details] [nvarchar](max) NULL,
[Inserted] [datetimeoffset](0) NOT NULL,
[Updated] [datetimeoffset](0) NOT NULL,
[InsertedBy] [int] NULL,
[UpdatedBy] [int] NULL,
)
For each changed column, I want to add a row to this table. This table will hold changes for the Item table, but later it will hold changes for other tables as well. I would like the trigger to be as dynamic as possible, so the same basic trigger can be used for other tables as well. If columns are added/removed to a table, the SP should discover that and not break.
CREATE TABLE [dbo].[Events]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [int] NOT NULL, -- Item.Id
[EventTypeId] [int] NOT NULL, -- Always 2
[EventDate] [datetimeoffset](0) NOT NULL, --GetUTCDate()
[ColumnName] [nvarchar](50) NULL, --The column name that changed
[OriginalValue] [nvarchar](max) NULL, --The original Value
[NewValue] [nvarchar](max) NULL, --The New Value
[TenantId] [int] NOT NULL, --Item.TentantId
[AppUserId] [int] NOT NULL, --Item.ModifiedBy
[TableName] [int] NOT NULL --The Name of the Table (Item in this case, but later there will be others)
)
I am trying to write an Update trigger, but am finding it difficult.
I know there is are Inserted and Deleted tables that hold the new and old values.
So how do I actually achieve that? It seems that it ought to be dynamic so that if columns are added, it doesn't break anything.
If I were writing this in C#, I would get all the column names and loop through them and find the changed fields, then create an Event for each of them. But I am don't see how to do this with SQL.
UPDATE TO RESPOND TO ANSWER:
This answer works when editing in SSMS. However, in practice, the app uses EntityFramework and it appears to be doing something strange, as this is what gets logged. Note that only one column actually had different values in Original/New. Thus I was trying to check that the values were actually different before doing the insert.
+----+----------+-------------+----------------------------+------------------+----------------------------+----------------------------+----------+-----------+---------+-----------+
| Id | RecordId | EventTypeId | EventDate | ColumnName | OriginalValue | NewValue | TenantId | AppUserId | TableId | TableName |
+----+----------+-------------+----------------------------+------------------+----------------------------+----------------------------+----------+-----------+---------+-----------+
| 21 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | Name | Task 2 | Task 2A | 8 | 11 | NULL | Item |
| 22 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | Description | NULL | NULL | 8 | 11 | NULL | Item |
| 23 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | ParentId | 238 | 238 | 8 | 11 | NULL | Item |
| 24 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | EntityStatusId | 1 | 1 | 8 | 11 | NULL | Item |
| 25 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | ItemTypeId | 3 | 3 | 8 | 11 | NULL | Item |
| 26 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | StartDate | NULL | NULL | 8 | 11 | NULL | Item |
| 27 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | DueDate | NULL | NULL | 8 | 11 | NULL | Item |
| 28 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | Budget | NULL | NULL | 8 | 11 | NULL | Item |
| 29 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | Cost | NULL | NULL | 8 | 11 | NULL | Item |
| 30 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | Progress | NULL | NULL | 8 | 11 | NULL | Item |
| 31 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | StatusTypeId | 1 | 1 | 8 | 11 | NULL | Item |
| 32 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | ImportanceTypeId | NULL | NULL | 8 | 11 | NULL | Item |
| 33 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | PriorityTypeId | NULL | NULL | 8 | 11 | NULL | Item |
| 34 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | OwnedBy | 11 | 11 | 8 | 11 | NULL | Item |
| 35 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | Details | <p><span></span></p> | <p><span></span></p> | 8 | 11 | NULL | Item |
| 36 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | Inserted | 0001-01-01 00:00:00 +00:00 | 0001-01-01 00:00:00 +00:00 | 8 | 11 | NULL | Item |
| 37 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | Updated | 0001-01-01 00:00:00 +00:00 | 0001-01-01 00:00:00 +00:00 | 8 | 11 | NULL | Item |
| 38 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | InsertedBy | 11 | 11 | 8 | 11 | NULL | Item |
| 39 | 397 | 2 | 2018-04-22 15:42:16 +00:00 | UpdatedBy | 11 | 11 | 8 | 11 | NULL | Item |
+----+----------+-------------+----------------------------+------------------+----------------------------+----------------------------+----------+-----------+---------+-----------+
Here's one way using COLUMNS_UPDATED. Trigger does not depend on column names, so you can add or remove columns without problem. I have added some comments in the query
create trigger audit on Items
after update
as
begin
set nocount on;
create table #updatedCols (Id int identity(1, 1), updateCol nvarchar(200))
--find all columns that were updated and write them to temp table
insert into #updatedCols (updateCol)
select
column_name
from
information_schema.columns
where
table_name = 'Items'
and convert(varbinary, reverse(columns_updated())) & power(convert(bigint, 2), ordinal_position - 1) > 0
--temp tables are used because inserted and deleted tables are not available in dynamic SQL
select * into #tempInserted from inserted
select * into #tempDeleted from deleted
declare #cnt int = 1
declare #rowCnt int
declare #columnName varchar(1000)
declare #sql nvarchar(4000)
select #rowCnt = count(*) from #updatedCols
--execute insert statement for each updated column
while #cnt <= #rowCnt
begin
select #columnName = updateCol from #updatedCols where id = #cnt
set #sql = N'
insert into [Events] ([RecordId], [EventTypeId], [EventDate], [ColumnName], [OriginalValue], [NewValue], [TenantId], [AppUserId], [TableName])
select
i.Id, 2, GetUTCDate(), ''' + #columnName + ''', d.' + #columnName + ', i.' + #columnName +', i.TenantId, i.UpdatedBy, ''Item''
from
#tempInserted i
join #tempDeleted d on i.Id = d.Id and isnull(Cast(i.' + #columnName + ' as varchar), '''') <> isnull(Cast(d.' +#columnName + ' as varchar), '''')
'
exec sp_executesql #sql
set #cnt = #cnt + 1
end
end
I have changed data type of TableName column of Events table to nvarchar.
You could query the catalog (sys.columns, sys.tables, sys.schemas, etc.) to get the columns of the current table into a cursor. Then iterate over that cursor and build your single inserts to the log table as string. Then execute them with EXECUTE or sp_executesql or similar.
(Note, that the linked documentation does not necessarily match the version of your DBMS and is just meant as a first hint.)
By the way, you might want to change the datatype of [TableName] and [ColumnName] to sysname which is also used in the catalog for such columns.
I have a table with start and end dates for team consultations with customers.
I need to merge certain consultations based on a number of days specified in another column (sometimes the consultations may overlap, sometimes they are contiguous, sometimes they arent), Team and Type.
Some example data is as follows:
DECLARE #TempTable TABLE([CUSTOMER_ID] INT
,[TEAM] VARCHAR(1)
,[TYPE] VARCHAR(1)
,[START_DATE] DATETIME
,[END_DATE] DATETIME
,[GROUP_DAYS_CRITERIA] INT)
INSERT INTO #TempTable VALUES (1,'A','A','2013-08-07','2013-12-31',28)
,(2,'B','A','2015-05-15','2015-05-28',28)
,(2,'B','A','2015-05-15','2016-05-12',28)
,(2,'B','A','2015-05-28','2015-05-28',28)
,(3,'C','A','2013-05-27','2014-07-23',28)
,(3,'C','A','2015-01-12','2015-05-28',28)
,(3,'B','A','2015-01-12','2015-05-28',28)
,(3,'C','A','2015-05-28','2015-05-28',28)
,(3,'C','A','2015-05-28','2015-12-17',28)
,(4,'A','B','2013-07-09','2014-04-21',7)
,(4,'A','B','2014-04-29','2014-08-01',7)
Which looks like this:
+-------------+------+------+------------+------------+---------------------+
| CUSTOMER_ID | TEAM | TYPE | START_DATE | END_DATE | GROUP_DAYS_CRITERIA |
+-------------+------+------+------------+------------+---------------------+
| 1 | A | A | 07/08/2013 | 31/12/2013 | 28 |
| 2 | B | A | 15/05/2015 | 28/05/2015 | 28 |
| 2 | B | A | 15/05/2015 | 12/05/2016 | 28 |
| 2 | B | A | 28/05/2015 | 28/05/2015 | 28 |
| 3 | C | A | 27/05/2013 | 23/07/2014 | 28 |
| 3 | C | A | 12/01/2015 | 28/05/2015 | 28 |
| 3 | B | A | 12/01/2015 | 28/05/2015 | 28 |
| 3 | C | A | 28/05/2015 | 28/05/2015 | 28 |
| 3 | C | A | 28/05/2015 | 17/12/2015 | 28 |
| 4 | A | B | 09/07/2013 | 21/04/2014 | 7 |
| 4 | A | B | 29/04/2014 | 01/08/2014 | 7 |
+-------------+------+------+------------+------------+---------------------+
My desired output is as follows:
+-------------+------+------+------------+------------+---------------------+
| CUSTOMER_ID | TEAM | TYPE | START_DATE | END_DATE | GROUP_DAYS_CRITERIA |
+-------------+------+------+------------+------------+---------------------+
| 1 | A | A | 07/08/2013 | 31/12/2013 | 28 |
| 2 | B | A | 15/05/2015 | 12/05/2016 | 28 |
| 3 | C | A | 27/05/2013 | 23/07/2014 | 28 |
| 3 | C | A | 12/01/2015 | 17/12/2015 | 28 |
| 3 | B | A | 12/01/2015 | 28/05/2015 | 28 |
| 4 | A | B | 09/07/2013 | 21/04/2014 | 7 |
| 4 | A | B | 29/04/2014 | 01/08/2014 | 7 |
+-------------+------+------+------------+------------+---------------------+
I am struggling to do this at all, let alone with any efficiency! Any ideas / code will be greatly received.
Server version is MS SQL Server 2014
Thanks,
Dan
If I am understanding your question correctly, we want to return rows only when a second, third, etc consultation has not occurred within group_days_criteria number of days after the previous consultation end date.
We can get the previous consultation end date and eliminate rows (since we are not concerned with the number of consultations) where a consultation occurred for the same customer by the same team and of the same consultation type within our date range.
DECLARE #TempTable TABLE([CUSTOMER_ID] INT
,[TEAM] VARCHAR(1)
,[TYPE] VARCHAR(1)
,[START_DATE] DATETIME
,[END_DATE] DATETIME
,[GROUP_DAYS_CRITERIA] INT)
INSERT INTO #TempTable VALUES (1,'A','A','2013-08-07','2013-12-31',28)
,(2,'B','A','2015-05-15','2015-05-28',28)
,(2,'B','A','2015-05-15','2016-05-12',28)
,(2,'B','A','2015-05-28','2015-05-28',28)
,(3,'C','A','2013-05-27','2014-07-23',28)
,(3,'C','A','2015-01-12','2015-05-28',28)
,(3,'B','A','2015-01-12','2015-05-28',28)
,(3,'C','A','2015-05-28','2015-05-28',28)
,(3,'C','A','2015-05-28','2015-12-17',28)
,(4,'A','B','2013-07-09','2014-04-21',7)
,(4,'A','B','2014-04-29','2014-08-01',7)
;with prep as (
select Customer_ID,
Team,
[Type],
[Start_Date],
[End_Date],
Group_Days_Criteria,
ROW_NUMBER() over (partition by customer_id, team, [type] order by [start_date] asc, [end_date] desc) as rn, -- earliest start date with latest end date
lag([End_Date] + Group_Days_Criteria, 1, 0) over (partition by customer_id, team, [type] order by [start_date] asc, [end_date] desc) as PreviousEndDate -- previous end date +
from #TempTable
)
select p.Customer_Id,
p.[Team],
p.[Type],
p.[Start_Date],
p.[End_Date],
p.Group_Days_Criteria
from prep p
where p.rn = 1
or (p.rn != 1 and p.[Start_date] > p.PreviousEndDate)
order by p.Customer_Id, p.[Team], p.[Start_Date], p.[Type]
This returned the desired result set.
I have two tables (each with about 20 columns), none of the column names match up but some of the values in 1 column match the values in another (see below).
I want to get a the combination of the 2 tables on certain columns based on True/False values in a column on the primary table.
I am doing all of this using the SQLServer Third Party JDBC Drivers in Oracle's SQL Developer (I am not sure if or how that might have an effect on my syntax).
I am sure that this is simple, but I cannot find any examples that do this and I am just too new to SQL to wrap my head around it.
CREATE TABLE [dbo].[TableA] (
[colA1] VARCHAR (10) NULL,
[colA2] VARCHAR (10) NULL,
[colA3] VARCHAR (10) NULL,
[colA4] VARCHAR (10) NULL,
[colA5] VARCHAR (10) NULL,
[colA6] INT NULL,
[colKey] INT NOT NULL,
CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED ([colKey] ASC)
);
CREATE TABLE [dbo].[TableB] (
[colB1] VARCHAR (10) NULL,
[colB2] VARCHAR (10) NULL,
[colB3] VARCHAR (10) NULL,
[colB4] INT NULL,
[colKey] INT NOT NULL,
PRIMARY KEY CLUSTERED ([colKey] ASC)
);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (1,'AC1-1','AC2-1','AC3-1',NULL,'FALSE',2016);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (2,'AC1-2','AC2-2','AC3-2',NULL,'FALSE',2016);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (3,'AC1-3',NULL,NULL,'AC4-3','TRUE',2016);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (4,'AC1-4',NULL,NULL,'AC4-4','TRUE',2016);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (5,'AC1-5','AC2-5','AC3-5',NULL,'FALSE',2015);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (6,'AC1-6','AC2-6','AC3-6',NULL,'FALSE',2015);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (7,'AC1-7',NULL,NULL,'AC4-7','TRUE',2015);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (8,'AC1-8',NULL,NULL,'AC4-8','TRUE',2015);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (9,'AC1-9',NULL,NULL,'AC4-9','TRUE',2016);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (1,'AC4-3','BC2-1','BC3-1',2015);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (2,'AC4-4','BC2-2','BC3-2',2015);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (3,'AC4-4','BC2-3','BC3-3',2016);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (4,'AC4-3','BC2-4','BC3-4',2016);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (5,'AC4-7','BC2-5','BC3-5',2015);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (6,'AC4-8','BC2-6','BC3-6',2015);
TableA
+-------+--------+--------+--------+-------+-------+
| colA1 | colA2 | colA3 | colA4 | colA5 | colA6 |
+-------+--------+--------+--------+-------+-------+
| AC1-1 | AC2-1 | AC3-1 | (Null) | FALSE | 2016 |
| AC1-2 | AC2-2 | AC3-2 | (Null) | FALSE | 2016 |
| AC1-3 | (Null) | (Null) | AC4-3 | TRUE | 2016 |
| AC1-4 | (Null) | (Null) | AC4-4 | TRUE | 2016 |
| AC1-5 | AC2-5 | AC3-5 | (Null) | FALSE | 2015 |
| AC1-6 | AC2-6 | AC3-6 | (Null) | FALSE | 2015 |
| AC1-7 | (Null) | (Null) | AC4-7 | TRUE | 2015 |
| AC1-8 | (Null) | (Null) | AC4-8 | TRUE | 2015 |
| AC1-9 | (Null) | (Null) | AC4-9 | TRUE | 2016 |
+-------+--------+--------+--------+-------+-------+
TableB
+-------+-------+-------+-------+
| colB1 | colB2 | colB3 | colB4 |
+-------+-------+-------+-------+
| AC4-3 | BC2-1 | BC3-1 | 2015 |
| AC4-4 | BC2-2 | BC3-2 | 2015 |
| AC4-4 | BC2-3 | BC3-3 | 2016 |
| AC4-3 | BC2-4 | BC3-4 | 2016 |
+-------+-------+-------+-------+
Results Table
+-------+--------+-------+-------------------------+-------------------------+
| colA1 | colA4 | colA5 | combined(colA2 & colB2) | combined(colA3 & colB3) |
+-------+--------+-------+-------------------------+-------------------------+
| AC1-1 | (null) | FALSE | AC2-1 | AC3-1 |
| AC1-2 | (null) | FALSE | AC2-2 | AC3-2 |
| AC1-3 | AC4-3 | TRUE | BC2-1 | BC3-1 |
| AC1-4 | AC4-4 | TRUE | BC2-2 | BC3-2 |
| AC1-9 | AC4-9 | TRUE | (null) | (null) |
+-------+--------+-------+-------------------------+-------------------------+
So I think I need some kind of SELECT like this:
SELECT colA1, colA5,
IF colA5 = True
THEN colB2, colB3, etc.
ELSE colA2, ColA3, etc.
FROM tableB, tableA
WHERE colA1 = colB1 AND colB4 = 2016 AND colA6 = 2016
I have tried this:
SELECT A.colA1
,A.colA4
,A.colA5
,CASE
WHEN A.colA5 = TRUE
THEN B.colB2
ELSE A.colA2
END AS 'combined(colA2 & colB2)'
,CASE
WHEN A.colA5 = TRUE
THEN B.colB3
ELSE A.colA4
END AS 'combined(colA3 & colB3)'
,
FROM TableA A
,TableB B
WHERE A.colA6 = '2016'
AND B.colB4 = '2016'
AND (
A.colA4 = B.colB1
OR A.colA4 IS NULL
)
what I get is this:
+-------+-------+-------+-------------------------+-------------------------+
| colA1 | colA4 | colA5 | combined(colA2 & colB2) | combined(colA3 & colB3) |
+-------+-------+-------+-------------------------+-------------------------+
| AC1-3 | AC4-3 | TRUE | BC2-1 | BC3-1 |
| AC1-4 | AC4-4 | TRUE | BC2-2 | BC3-2 |
+-------+-------+-------+-------------------------+-------------------------+
So I am missing the rows were TableA/colA5 are FALSE. Also, I need 12 of these "combined" columns, is there a way that I can avoid using 12 CASE statements?
After learning about joins and case here is the answer (though apparently I will have to use the 12 CASE statements that I would have preferred to avoid).
SELECT A.colA1
,A.colA4
,A.colA5
,CASE
WHEN A.colA5 = 'TRUE'
THEN B.colB2
ELSE A.colA2
END AS 'combined(colA2 & colB2)'
,CASE
WHEN A.colA5 = 'TRUE'
THEN B.colB3
ELSE A.colA3
END AS 'combined(colA3 & colB3)'
FROM TableA A LEFT JOIN TableB B ON A.colA4 = B.colB1
WHERE (A.colA6 = '2016' and A.colA5 ='FALSE')
or (A.colA6 = '2016' and A.colA5 ='true' and B.colB4 = '2016')
or (A.colA6 = '2016' and A.colA5 ='true' and B.colB4 is null)
;
I created a table managers :
create table managers(
ManagerId int identity(1,1) not for replication not null,
M_name varchar(20),
Salary varchar(20),
joining_year varchar(20),
city varchar(20),
IdCode int
)
then insert some data into this table:
ManagerId | M_name | Salary | joining_year | city | IdCode
----------------------------------------------------------------------
1 | riva | 50000 | 1998 | pune | 4
2 | tanmay | 48500 | 1990 |gurgaon | 2
3 | david | 49000 | 2001 | goa | 2
4 | null | null | null | null | null
5 | null | null | null | null | null
6 | dannial | 52185 | 2010 | kanpur | 6
And have second table managerEmp
create table managerEmp(
employeId int identity(1,1) not for replication not null,
family_member varchar(20),
wife_name varchar(20),
age int
)
I have some data in that table:
employeId | family_member |wife_name | age
--------------------------------------------
1 | 6 |mrs.kapoor| 31
2 | 5 |mrs.mishra| 25
3 | null |nll | null
4 | 2 |mrs.khan | 21
5 | 4 |mrs.bajaj | 22
Now, I want to select uncommon data from that table. The result would be:
M_name | Salary | city | wife_name | age
-----------------------------------------
null | null | null | mrs.khan | 21
null | null | null | mrs.bajaj | 22
dannial| 52185 |kanpur| null |null
Query based on your output:
SELECT M_name,Salary,city,wife_name,age FROM managers LEFT JOIN managerEmp
ON managers.ManagerId =managerEmp.employeId
WHERE M_name is NULL OR employeId IS NULL
Link to SQL fiddle http://sqlfiddle.com/#!6/e1776/1