Acquiring Row index with identity column in Join Query - sql-server

I need to add the results from a Left Join query to a table that does not have its index set to be an identity, but the int must still be unique. My insert query looks like this:
INSERT INTO Table1 (S.SubjectID, S.Subject, S.SubjectDescription, S.Status)
SELECT (Select MAX(SubjectID) FROM Table1) + ???? , N.Code, N.Literal, N.Trans
FROM Table2 N LEFT JOIN Table1 S ON N.Code = S.Subject
WHERE (N.Code IS NULL OR S.Subject IS NULL OR N.Trans = 'D')
Where I have the ???? is where i need to have some incrementing value so that when inserting into the table1 the ID's will be unique.
I am not allowed to change the table's structure, I just need something that can calculate his on the fly.
As always help, tips and references are much appreciated.

In most databases, you can use row_number() for this purpose. Here is an example with SQL Server syntax:
INSERT INTO Table1 (S.SubjectID, S.Subject, S.SubjectDescription, S.Status)
SELECT (Select MAX(SubjectID) FROM Table1) + row_number() over (order by (select NULL)) ,
N.Code, N.Literal, N.Trans
FROM Table2 N LEFT JOIN Table1 S ON N.Code = S.Subject
WHERE (N.Code IS NULL OR S.Subject IS NULL OR N.Trans = 'D')

Related

Multiple OR operator in Snowflake in WHERE Clause is not working

I am trying to do below
Table 1
Table 2
I am writing a query like below to ensure that if any of the NOT IN satisfies, those records should be filtered out.
SELECT * FROM TABLE1
WHERE TABLE1."DEPTID" NOT IN (SELECT TABLE2."DEPTID" FROM TABLE2)
OR
TABLE1."EMPCOUNTRY" NOT IN (SELECT TABLE2."EMPCOUNTRY" FROM TABLE2)
OR
TABLE1."EMPZONE" NOT IN (SELECT TABLE2."EMPZONE" FROM TABLE2)
But it errors out
What am I doing wrong?
Edited : Exact Query is working with nvl , but result set is not as per requirement.
SELECT * FROM TABLE1 AS T1
WHERE
(
UPPER (T1."DEPTID") NOT IN
(SELECT UPPER (nvl (T2."DEPTID", '')) FROM TABLE2 AS T2)
OR
UPPER (T1."EMPZONE") NOT IN
(SELECT UPPER (nvl (T2."EMPZONE",'')) FROM TABLE2 AS T2)
)
Result - set is not as per requirement, it should filter out if there any DEPTID in the Table2 or if there is any EMPZONE in table 2 or both etc.
What should be the best way to achieve this?
I think the issue is about NULL values coming from the subqueries. Could you try to use something like this?
SELECT * FROM TABLE1 AS T1
WHERE
(
NOT EXISTS (SELECT 1 FROM TABLE2 T2 WHERE equal_null( UPPER(T1."DEPTID"), UPPER(T2."DEPTID")) )
OR
NOT EXISTS (SELECT 1 FROM TABLE2 T2 WHERE equal_null( UPPER(T1."EMPZONE"), UPPER(T2."EMPZONE")) )
);
Also here is a sample to demonstrate why you can't use NOT IN with a subquery returning NULL values:
create table NULL_TABLE ( v varchar);
insert into NULL_TABLE values (NULL),('ABC');
create or replace table MAIN_TABLE ( v varchar);
INSERT INTO MAIN_TABLE values
('Jack'),('Joe'),('ABC');
select * from MAIN_TABLE
where v NOT IN (select v FROM NULL_TABLE);
The last query returns NULL, because we can't determine if a value does not exist in series of numbers where some of them are not known - the last WHERE clause.
When using NOT IN the subquery should not allow null values as reselut, second conditions to happen all at once should be joined with AND instead of OR.
NOT (cond1 OR cond2 OR cond3)
<=>
(NOT cond1) AND (NOT cond2) AND (NOT cond3)
De Morgan's law: "The negation of a disjunction is the conjunction of the negations"
The final query should rather be:
SELECT *
FROM TABLE1 AS T1
WHERE T1."DEPTID" NOT IN (SELECT T2."DEPTID" FROM TABLE2 T2
WHERE T2."DEPTID" IS NOT NULL)
AND T1."EMPCOUNTRY" NOT IN (SELECT T2."EMPCOUNTRY" FROM TABLE2 T2
WHERE T2."EMPCOUNTRY" IS NOT NULL)
AND T1."EMPZONE" NOT IN (SELECT T2."EMPZONE" FROM TABLE2 T2
WHERE T2."EMPZONE" IS NOT NULL);

Find most recent date for ID with multiple records in MS Access

I have a field, "ID", and it has repeat values. (In the example; A21, B42, and C14). My two other fields in the table are "Date" and "Measurement". I want to create a query that will call the previous date WITH matching ID and display the results of that previous row. My end goal is to have a field in my query that will find the change between the current measurement for the ID and the measurement from the date prior.
I have attached an image of the table I have and what I want the query to display.
Sadly MS Access does not support lag(). This however can be emulated with a self-join and a not exists condition with a correlated subquery:
select
t.id,
tprev.date as previous_date,
tprev.measureement as previous_measurement
from Table1 as t
left join Table1 as tprev
on (tprev.id = t.id)
and (tprev.dat < t.date)
and (not exists (
select 1
from Table1 as t1
where
t1 = t.id
and t1.dat < t.date
and t1.dat > tprev.date
))
This is how to make the described query function:
SELECT t.NUM, t.ID, tprev.Date_ AS previous_date, tprev.Measurement AS previous_measurement
FROM Table1 AS t LEFT JOIN Table1 AS tprev ON (tprev.Date_ < t.Date_) AND (tprev.id = t.id)
WHERE not exists
(select 1
from Table1 AS t1
where
t1.ID = t.ID
and t1.Date_ < t.Date_
and t1.Date_ > tprev.Date_);

How to concatenate 3 tables MSSQL Server

In a single database, I have three tables as below:
I want to concatenate them in some single table, any suggestion?
If I am understanding correctly your answer you want something like this:
CREATE TABLE COMBINED (/*Insert the set of fields here*/);
GO
INSERT INTO COMBINED
SELECT Table1.ProposalId
, /*all other Table1 fields*/
, Table2.ProposalId
/*all other Table2 fields*/
, Table3.ProposalId
, /*all other Table2 fields*/
FROM Table1
FULL JOIN Table2
ON Table1.ProposalId = Table2.ProposalId
FULL JOIN Table3
ON Table1.ProposalId = Table3.ProposalId;
This will match the rows with the same proposal id (but keep the all the its values as proposalid_1,proposalid_2... and for those that do not match will bring the full row and NULL for every other fields of the rest of the tables.
Thanks for your help the issue has been solved.
SELECT mtlreq.proposalid, mtlreq.prp_mtlreq_taskgrp,mtlreq.prp_mtlreq_taskcode,mtlreq.prp_mtlreq_itemcode,mtlreq.prp_mtlreq_rateper,mtlreq.prp_mtlreq_qty,mtlreq.prp_mtlreq_Inter_MaterCost,mtlreq.prp_mtlreq_UOM,mtlreq.item_short_desc, resreq.proposalid,resreq.prp_resreq_taskcode ,resreq.prp_resreq_resource,resreq.prp_resreq_usage,resreq.prp_resreq_uom,resreq.prp_resreq_rate,resreq.prp_resreq_overhd_pers
FROM (
SELECT proposalid,prp_mtlreq_taskgrp,prp_mtlreq_taskcode,prp_mtlreq_itemcode,prp_mtlreq_rateper,prp_mtlreq_qty,prp_mtlreq_Inter_MaterCost,prp_mtlreq_UOM,item_short_desc,
ROW_NUMBER() OVER (ORDER BY proposalid) AS rn
FROM prjdet_prp_taskwork_mtlreq ) AS mtlreq
FULL OUTER JOIN (
SELECT proposalid,prp_resreq_taskcode ,prp_resreq_resource,prp_resreq_usage,prp_resreq_uom,prp_resreq_rate,prp_resreq_overhd_pers,
ROW_NUMBER() OVER (ORDER BY proposalid) AS rn
FROM prjdet_prp_taskwork_resreq) AS resreq
ON mtlreq.rn = resreq.rn
FULL OUTER JOIN (
SELECT proposalid,mtprp_delv_lineno,mtprp_delv_itemcode,mtprp_delv_cost,mtprp_delv_linelevelmrg,mtprp_delv_proposedamt,
ROW_NUMBER() OVER (ORDER BY proposalid) AS rn
FROM prjproposal_delidtl ) AS delidtl
on mtlreq.rn = delidtl.rn and resreq.rn=delidtl.rn

SQL Server stored procedure select, exists, multiple tables

Any method to do this?
Table1
1
2
3
4
5
Table2
3 (with the condition)
4 (without the condition)
I want to:
Select all records from Table1 if it exists in Table 2, where...(condition)
Select all records from Table1 if it not exists in Table2
Combine both select results. Sort all results with their created date.
For example, the result should be:
Result
1
2
3
5
Hopefully this can help.
SELECT t1.* from table1 t1
JOIN table2 t2
ON t1.ID = t2.ID
UNION ALL
SELECT t1.* from table1 t1 where ID in
(
SELECT t2.ID from table1 t1 except Select t2.ID from table2 t2
)
ORDER BY t1.CreatedDate
You can achieve this by doing:
SELECT t1.id
FROM Table1 t1
LEFT JOIN Table2 t2 on t1.id = t2.id
WHERE condition OR t2.id IS NULL
ORDER BY t1.CreatedDate;
See fiddle (I assumed condition to be t2.id!=4, but it can be anything else depending on other data in your tables).
There could be multiple solution.
One way
we can get the result set using two different queries and at last combine both of the result-set using UNION
Another way,
First statement is saying that get all the result set from TABLE1 if it exists in TABLE2 as well with some criteria (condition in where clause)
means using INNER JOIN we can achieve this
Second statement is saying get all the result set from TABLE1 which are not present in TABLE2
means along with INNER JOIN ed query also include the TABLE1's data if not present in TABLE2
here we can take the help of LEFT OUTER JOIN (taking TABLE1 on the left side)
Assumption: (condition: t1.Id != 4)
Let's try to understand the query using both of the above mentioned ways
---- -- --Step1 Create table and insert records
---- create table1 with Id int identity columsn
--CREATE TABLE Table1 (Id INT IDENTITY(1,1), CreatedDate smalldatetime default(getdate()));
--go
---- insert 1st 5 integers into Table1
--INSERT INTO Table1 DEFAULT VALUES
--go 5
---- create Table2 with Id int column
--CREATE TABLE Table2 (Id INT , CreatedDate smalldatetime default(getdate()));
--go
---- insert records 3,5 into Table2
--INSERT INTO Table2(Id) VALUES (3), (4);
-- -- -- Solution: one way
; WITH cteMyFirstResult AS
(
-- 2.1. Select all records from Table1 if it exists in Table 2, where...(condition)
SELECT
Id, CreatedDate
FROM Table1 AS t1
WHERE t1.Id IN (SELECT Id FROM Table2 AS t2)
AND t1.Id != 4 -- assumption it can be any condition
),cteMySecondResult AS (
-- 2.2. Select all records from Table1 if it not exists in Table2
SELECT
Id, CreatedDate
FROM Table1 AS t1 WHERE t1.Id NOT IN (SELECT Id FROM Table2 AS t2)
)
-- 2.3. Combine both select results. Sort all results with their created date.
SELECT
Id, CreatedDate
FROM cteMyFirstResult
UNION
SELECT
Id, CreatedDate
FROM cteMySecondResult
ORDER BY CreatedDate;
-- -- Solution: Another way (with bug)
SELECT t1.Id, t1.CreatedDate
FROM Table1 AS t1
LEFT JOIN Table2 AS t2 on t1.id = t2.id
WHERE t1.Id != 4
Order by T1.CreatedDate;
-- in this query we are using the criteria after doing the join operation.
-- thus after filtering out the result set based on JOIN Condition this condition will get applied
-- and if there is any null record in the Table1 for column Id (used in join) will not come in the final result-set
-- to avoid this we can include NULL check along with our criteria
-- -- Solution: Another way
SELECT t1.Id, t1.CreatedDate
FROM Table1 AS t1
LEFT JOIN Table2 AS t2 on t1.id = t2.id
WHERE ( t1.Id != 4 ) OR t1.Id IS NULL -- include all your criteria within small-barcket)
Order by T1.CreatedDate;
Thanks for all responses.
I come out with the answer I want:
SELECT *
FROM Table1 t1
WHERE NOT EXISTS(SELECT 1 FROM Table2 t2
WHERE t1.ID = t2.ID
AND t2.CIF_KEY = #CifKey
AND t2.STATUS <> ''3'')
AND (condition in where clause)

List data in a table that is not in a view

Table1 has columns
Id int, Date smalldatetime.
View1 has, among many other columns, column Id int.
View1 has a maximum of 2000 rows, but there are some rather complex computation to determine the values of all the columns.
What is the most efficient way to return all Table1.Id that are not in View1.Id for Table1.Date between '2012-05-30' and '2012-05-31' ?
The filtered selection from Table1 typically returns about 200 unique Table1.Id.
When I do a SELECT * FROM View1, the total data is returned always in under one second. When I do a SELECT Id from Table1 WHERE Date BETWEEN '2012-05-30' AND '2012-05-31', the result is always instanteous.
The moment I tried SELECT Table1.Id from Table1 T1 WHERE Date BETWEEN .. AND .. AND NOT EXISTS (SELECT Id from View1 WHERE ViewId=T1.Id), it takes ages (almost 20s).
I tried using a CTE also, WITH V1 as (SELECT Id from View1) SELECT T1.Id FROM Table1 T1 WHERE Date BETWEEN ... and ... AND NOT EXISTS (SELECT Id from V1 WHERE V1.Id=T1.Id), and it also took ages.
Thanks.
Try something like this:
SELECT t.Id, t.[Date]
FROM dbo.Table1 AS t
LEFT HASH JOIN dbo.View1 AS v ON v.Id = t.Id
WHERE t.[Date] >= '20120530' AND t.[Date] < '20120531'
AND v.Id IS NULL
The HASH hint forces the SQL Server query optimizer to evaluate the view only once.
Another way would be to use a table variable to store the result of the view:
DECLARE #ViewResult TABLE (Id int PRIMARY KEY)
INSERT INTO #ViewResult
SELECT Id FROM dbo.View1
SELECT Id, [Date]
FROM dbo.Table1
WHERE [Date] >= '20120530' AND [Date] < '20120531'
AND Id NOT IN (SELECT Id FROM #ViewResult)
Razvan
With little else to go on, I would say that if the view must be referenced then:
SELECT t.Id, t.[Date]
FROM dbo.Table1 AS t
WHERE t.[Date] >= '20120530'
AND t.[Date] < '20120531'
AND NOT EXISTS
(
SELECT 1 FROM dbo.View1 AS v
WHERE v.Id = t.Id
);
But I suspect you can do something more efficient here if you can bypass the view.

Resources