Nightmare Case Statement Assistance pl - sql

Table 1 - Deal ID, REF NOS, Type, Papa ID
Table 2 - Deal ID, Type
Making a column in a new view called Method used. The way the field is to be set is as follows ( 4 conditions);
If Deal ID from table 1 Exists in Table 2 and Type is not Null from Table 2.
Set Method used to be Y
If Deal ID does not exist in Table 1 and Type does not contain 27,42 or 55 in Table 1.
Set Method used to be Y
If Papa ID is null from Table 1, and Type does not contain 27,42 or 55 in Table 1.
Set Method used to be Y
Else
Set to N
Started it and thought wow!..
create view Master as (
select Deal ID, REF NOS, Type, Papa ID
[Method used]=
Case
When
from Table 1 A
)

Something like this may work (assuming that these tables join on DealId). Note, I've removed spaces from some of your column names that you showed in your question.
Given these tables:
CREATE TABLE #Table1 (DealId INT, RefNos VARCHAR(100), [Type] VARCHAR(100), PapaId INT);
CREATE TABLE #Table2 (DealId INT, [Type] VARCHAR(100));
view example:
WITH DealIds AS (
SELECT DealId FROM #Table1
UNION
SELECT DealId FROM #Table2
)
SELECT
CASE
-- If Deal ID from table 1 Exists in Table 2 and Type is not Null from Table 2.
-- Set Method used to be Y
WHEN t1.DealId IS NOT NULL AND t2.DealId IS NOT NULL AND t2.[Type] IS NOT NULL THEN 'Y'
-- If Deal ID does not exist in Table 1 and Type does not contain 27,42 or 55 in Table 1.
-- Set Method used to be Y
-- Note: it is is redundant to have the type condition if DealId is the PK.
WHEN t1.DealId IS NULL AND t1.[Type] NOT IN (27, 42, 55) THEN 'Y'
-- If Papa ID is null from Table 1, and Type does not contain 27,42 or 55 in Table 1.
-- Set Method used to be Y
WHEN t1.PapaId IS NULL AND t1.[Type] NOT IN (27,42, 55) THEN 'Y'
-- Else
-- Set to N
ELSE 'N'
END AS MethodUsed
FROM DealIds d
LEFT JOIN #Table1 t1 ON d.DealId = t1.DealId
LEFT JOIN #Table2 t2 ON d.DealId = t2.DealId

Related

How to get in which criteria the range falls using sql query?

Code:
IF OBJECT_ID('tempdb..#TempMaster','U') IS NOT NULL
DROP TABLE #TempMaster
IF OBJECT_ID('tempdb..#TempTransaction','U') IS NOT NULL
DROP TABLE #TempTransaction
CREATE TABLE #TempMaster
(
Sno INT IDENTITY(1,1),
RangeDesc VARCHAR(100),
RangeFromValue INT,
RangeToValue INT
)
CREATE TABLE #TempTransaction
(
Sno INT IDENTITY(1,1),
[Values] INT
)
INSERT INTO #TempMaster(RangeDesc,RangeFromValue,RangeToValue)
SELECT * FROM (VALUES('Type A',1,10),('Type B',11,20),('Type C',21,30)) AS T(RangeDesc,RangeFromValue,RangeToValue)
INSERT INTO #TempTransaction([Values])
SELECT 1
UNION ALL
SELECT 15
UNION ALL
SELECT 5
SELECT * FROM #TempMaster
SELECT * FROM #TempTransaction
Please anyone help me to get a this kind of a solution based on which range the value falls.
I want to get a range description and write down a query for a below output. Thanks in advance.
-------------------------------
sno Values RangeDesc
-------------------------------
1 1 Type A
2 15 Type B
3 5 Type A
-------------------------------
You do left join based on range values.
select t1.Sno, t1.[Values], t2.RangeDesc
from #TempTransaction t1
left join #TempMaster t2 on t1.[Values] between t2.RangeFromValue and t2.RangeToValue

Copy data from one table to another in sql server

Consider the below tables.
Table 1:
ID Name Address DateOfBirth DateOfJoin CurrentProject
Table 2:
ID Name DateOfJoin CurrentProject
How do i write a sql server db script to copy data from Table 2 to Table 1 such that, values of Table 2 should overwrite values of Table 1 while merging except for when Table 2 value is null.
In case, the value of table 2 is null, the value of table 1 will take precedence.
Example in the above tables, the values of DataofJoin and CurrentProject should become values in the table 1 for a specific ID. When DateOfJoin and CurrentProject values are null in table 2, then table 1 value will remain as it is. Also, all the IDs that are present in Table 2 but not in Table 1 should be copied to Table 1 after running the script.
BEGIN
CREATE TABLE #Table1(
ID INT,
Name VARCHAR(50),
Address VARCHAR(50),
DateOfBirth DATE,
DateOfJoin DATE,
CurrentProject VARCHAR(50)
)
CREATE TABLE #Table2(
ID INT,
Name VARCHAR(50),
DateOfBirth DATE,
DateOfJoin DATE,
CurrentProject VARCHAR(50)
);
INSERT INTO #Table1 VALUES
(1,'NAME 1','ADDRESS 1','01/01/1990','01/01/2017','PROJECT 1'),
(2,'NAME 1','ADDRESS 2','01/01/1991','01/01/2017','PROJECT 2'),
(3,'NAME 1','ADDRESS 3','01/01/1992','01/01/2017','PROJECT 3'),
(4,'NAME 1','ADDRESS 4','01/01/1993','01/01/2017','PROJECT 4');
INSERT INTO #Table2 VALUES
(1,'NAME 1','01/01/1990','01/01/1988',NULL),
(3,'NAME 3','01/01/1991',NULL,'PROJECT 33'),
(5,'NAME 5','01/01/1986','01/01/2017','PROJECT 5'),
(6,'NAME 6','01/01/1985','01/01/2017','PROJECT 6');
SELECT * FROM #Table1;
SELECT * FROM #Table2;
-- Insert records which exists in Table but not in table 1
INSERT INTO #Table1(ID,Name,DateOfBirth,DateOfJoin,CurrentProject) SELECT * FROM #Table2 WHERE ID not in (SELECT ID FROM #table1)
-- Update matching id records from table 1 with table 2
UPDATE #Table1 SET
Name = CASE WHEN T2.Name='' or T2.Name IS NULL THEN #Table1.Name ELSE T2.Name END,
DateOfBirth = CASE WHEN T2.DateOfBirth='' or T2.DateOfBirth IS NULL THEN #Table1.DateOfBirth ELSE T2.DateOfBirth END,
DateOfJoin = CASE WHEN T2.DateOfJoin='' or T2.DateOfJoin IS NULL THEN #Table1.DateOfJoin ELSE T2.DateOfJoin END,
CurrentProject = CASE WHEN T2.CurrentProject='' or T2.CurrentProject IS NULL THEN #Table1.CurrentProject ELSE T2.CurrentProject END
FROM #Table2 T2 WHERE #Table1.ID= T2.ID
select * from #Table1
drop table #Table1;
drop table #Table2;
END

Inserting an auto generated value into a column with specific pattern

I have a table named tblSample which has columns ID, PID etc. I want to auto generate those two columns with a specific pattern.
For example:
ID PID
------ ------
ABC001 PAB001
ABC002 PAB002
ABC003 PAB003
ABC004 PAB004
| |
| |
ABC999 PAB999
As you can see, the pattern 'ABC' in ID and 'PAB' in PID is the same. How can I insert those records into a table automatically and the range between those three digits after 'ABC' or 'PAB' is 001-999?
My suggestion is to create table structure as below with one identity column as testID and other computed by using that column ID and PID:
CREATE TABLE #tmpOne(testID INT IDENTITY (1,1),
ID AS ('ABC'+ (CASE WHEN len(testID) <=3 THEN CAST(RIGHT(0.001*testID, 3) AS VARCHAR) ELSE CAST(testID AS VARCHAR) END)),
Ename VARCHAR(20))
INSERT INTO #tmpOne(Ename)
SELECT 'Test'
SELECT * FROM #tmpOne
CREATE TABLE #tt(ID VARCHAR(100),PID VARCHAR(100))
GO
INSERT INTO #tt(ID,PID)
SELECT 'ABC'+RIGHT('000'+LTRIM(a.ID),3),'PAB'+RIGHT('000'+LTRIM(a.ID),3) FROM (
SELECT ISNULL(MAX(CASE WHEN SUBSTRING(t.id,4,LEN(ID))> SUBSTRING(t.id,4,LEN(PID)) THEN SUBSTRING(t.id,4,LEN(ID)) ELSE SUBSTRING(t.id,4,LEN(PID)) END )+1,1) AS id
FROM #tt AS t
) AS a
GO 999

SQL Many to Many relationship

I'm having difficulties writing a SQL query. This is the structure of 3 tables, table Race_ClassificationType is many-to-many table.
Table Race
----------------------------
RaceID
Name
Table Race_ClassificationType
----------------------------
Race_ClassificationTypeID
RaceID
RaceClassificationID
Table RaceClassificationType
----------------------------
RaceClassificationTypeID
Name
What I'm trying to do is get the races with certain classifications. The results are returned by a store procedure that has a table-value parameter which holds the desired classifications:
CREATE TYPE [dbo].[RaceClassificationTypeTable]
AS TABLE
(
RaceClassificationTypeID INT NULL
);
GO
CREATE PROCEDURE USP_GetRaceList
(#RaceClassificationTypeTable AS [RaceClassificationTypeTable] READONLY,
#RaceTypeID INT = NULL,
#IsCompleted BIT = NULL,
#MinDateTime DATETIME = NULL,
#MaxDateTime DATETIME = NULL,
#MaxRaces INT = NULL)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT
R.[RaceID]
,R.[RaceTypeID]
,R.[Name]
,R.[Abbreviation]
,R.[DateTime]
,R.[IsCompleted]
FROM [Race] R,[Race_ClassificationType] R_CT, [RaceClassificationType] RCT
WHERE (R.[RaceTypeID] = #RaceTypeID OR #RaceTypeID IS NULL)
AND (R.[IsCompleted] = #IsCompleted OR #IsCompleted IS NULL)
AND (R.[DateTime] >= #MinDateTime OR #MinDateTime IS NULL)
AND (R.[DateTime] <= #MaxDateTime OR #MaxDateTime IS NULL)
AND (R.RaceID = R_CT.RaceID)
AND (R_CT.RaceClassificationTypeID = RCT.RaceClassificationTypeID)
AND (RCT.RaceClassificationTypeID IN (SELECT DISTINCT T.RaceClassificationTypeID FROM #RaceClassificationTypeTable T))
ORDER BY [DateTime] DESC
OFFSET 0 ROWS FETCH NEXT #MaxRaces ROWS ONLY
END
GO
As it is this stored procedure doesnt work correctly because it returns all races that have at least one classification type ID in the table-value parameter of classification type IDs (because of the IN clause). I want that the store procedure returns only races that have all the classifications supplied in the table-valued parameter.
Example:
RaceClassificationTypeID RaceID
3 92728
3 92729
8 92729
29 92729
12 92729
2 92729
3 92730
8 92730
8 92731
1 92731
RaceClassificationTypeIDs in RaceClassificationTypeTable parameter: 3 and 8
OUTPUT: all the races with RaceClassificationID 3 and 8 and optionally any other (2, 29, 12)
That means only races 92729 and 92730 should be returned, as it is all the races in the example are returned.
I've set up two tables, one stores your result set and the other represents the values in the table valued parameter of your stored procedure. See below.
CREATE TABLE ABC
(
RCTID INT,
RID INT
)
INSERT INTO ABC VALUES (3,92728)
INSERT INTO ABC VALUES (3,92729)
INSERT INTO ABC VALUES (8,92729)
INSERT INTO ABC VALUES (29,92729)
INSERT INTO ABC VALUES (12,92729)
INSERT INTO ABC VALUES (2,92729)
INSERT INTO ABC VALUES (3,92730)
INSERT INTO ABC VALUES (8,92730)
INSERT INTO ABC VALUES (8,92731)
INSERT INTO ABC VALUES (1,92731)
GO
CREATE TABLE TABLEVALUEPARAMETER
(
VID INT
)
INSERT INTO TABLEVALUEPARAMETER VALUES (3)
INSERT INTO TABLEVALUEPARAMETER VALUES (8)
GO
SELECT RID FROM ABC WHERE RCTID IN (SELECT VID FROM TABLEVALUEPARAMETER) GROUP BY
RID HAVING COUNT(RID) = (SELECT COUNT(VID) FROM TABLEVALUEPARAMETER)
GO
If you run this on your machine you'll notice it produces the two IDs that you're after.
Because you have a stored procedure with a lot of columns selected it would be necessary to use a CTE (Common Table Expression). This is because if you were to try to group all the columns in the current select statement you would have to group by all the columns and you would then get duplication.
If the first CTE delivers the result set and then you uses a version of the select above you should be able to produce only the IDs you want.
If you don't know CTE's let me know!
This is an example of a "set-within-sets" subquery. One way to solve this is with aggregation and a having clause. Here is how you get the RaceIds:
select RaceID
from RaceClassification rc
group by RaceID
having sum(case when RaceClassificationTypeId = 3 then 1 else 0 end) > 0 and
sum(case when RaceClassificationTypeId = 8 then 1 else 0 end) > 0;
Each condition in the having clause is counts how many rows have each type. Only races with each (because of the > 0) are kept.
You can get all the race information by using this as a subquery:
select r.*
from Races r join
(select RaceID
from RaceClassification rc
group by RaceID
having sum(case when RaceClassificationTypeId = 3 then 1 else 0 end) > 0 and
sum(case when RaceClassificationTypeId = 8 then 1 else 0 end) > 0
) rc
on r.RaceID = rc.RaceId;
Your stored procedure seems to have other conditions. These can also be added in.

In a persisted field, how do you return the number of occurrences of a column within a different table's column

The following is required due to records being entered by 3rd parties in a web application.
Certain columns (such as Category) require validation including the one below. I have a table OtherTable with the allowed values.
I need to identify how many occurrences (ie: IF) there are of the current table's column's value in a different table's specified column. If there are no occurrences this results in a flagged error '1', if there are occurrences, then it results in no flagged error '0'.
If `Category` can be found in `OtherTable.ColumnA` then return 0 else 1
How can I do this please?
If Category can be found in OtherTable.ColumnA then return 0 else 1
You could use CASE with EXISTS
SELECT CASE WHEN EXISTS(
SELECT NULL
FROM AllowedValues av
WHERE av.ColumnA = Category
) THEN 0 ELSE 1 END AS ErrorCode
, Category
FROM [Table]
Edit: Here's a sql-fiddle: http://sqlfiddle.com/#!3/55a2e/1
Edit: I've only just noticed that you want to use a computed column. As i've read you can only use it with scalar values and not with sub-queries. But you can create a scalar valued function.
For example:
create table AllowedValues(ColumnA varchar(1));
insert into AllowedValues Values('A');
insert into AllowedValues Values('B');
insert into AllowedValues Values('C');
create table [Table](Category varchar(1));
insert into [Table] Values('A');
insert into [Table] Values('B');
insert into [Table] Values('C');
insert into [Table] Values('D');
insert into [Table] Values('E');
-- create a scalar valued function to return your error-code
CREATE FUNCTION udf_Category_ErrorCode
(
#category VARCHAR(1)
)
RETURNS INT
AS BEGIN
DECLARE #retValue INT
SELECT #retValue =
CASE WHEN EXISTS(
SELECT NULL
FROM AllowedValues av
WHERE av.ColumnA = #category
) THEN 0 ELSE 1 END
RETURN #retValue
END
GO
Now you can add the column as computed column which uses the function to calculate the value:
ALTER TABLE [Table] ADD ErrorCode AS ( dbo.udf_Category_ErrorCode(Category) )
GO
Here's the running SQL: http://sqlfiddle.com/#!3/fc49e/2
Note: as #Damien_The_Unbelieve has commented at the other answer, even if you persist the result with a UDF, the value won't be updated if the rows in OtherTable change. Just keep that in mind, so you need to update the table manually if desired with the help of the UDF.
select mt.*,IFNULL(cat_count.ct,0) as Occurrences from MainTable mt
left outer join (select ColumnA,count(*) as ct from OtherTable) cat_count
on mt.Category=cat_count.ColumnA
Result:
mt.col1 | mt.col2 | Category | Occurrences
### | ### | XXX | 3
### | ### | YYY | 0
### | ### | ZZZ | 1