Find new dates for list of deals - sql

I want to find dates in calendar what not include in table with deals+dates columns by deals.
Example with expected result in code (T-SQL) . Thx for the advises
create table #deals
(id int ,
dates date);
create table #calendar
(dates date );
create table #result
(id int ,
dates date);
-----calendar table (tbl#1)
insert into #calendar values ('2020-04-19');
insert into #calendar values ('2020-04-20');
insert into #calendar values ('2020-04-21');
-----deals table (tbl#2)
insert into #deals values ('111', '2020-04-19');
insert into #deals values ('111', '2020-04-20');
insert into #deals values ('222', '2020-04-18');
----expected result table
insert into #result values ('111', '2020-04-21');
insert into #result values ('222', '2020-04-19');
insert into #result values ('222', '2020-04-20');
insert into #result values ('222', '2020-04-21');
select * from #calendar;
select * from #deals;
select * from #result

Generate all combinations of deals and dates and then remove the ones that exist:
select d.id, c.date
from (select distinct id from #deals) d cross join
#calendar c left join
#deals dd
on dd.id = d.id and dd.date = c.date
where dd.id is null;

Related

SQL Insert values by join

Perhaps it's too late and that's why I am stuck. I want to fill a database with values but only for those values where a date already exists in the data base. The structure is the following:
CREATE TABLE dbo.TEST(ID INT IDENTITY(1,1) NOT NULL,date_time datetime)
ALTER TABLE dbo.TEST ADD "column1" FLOAT;
INSERT INTO dbo.TEST(date_time,"column1")
VALUES ('2018-04-01 02:00:00',1),('2018-04-01 06:00:00',2),('2018-04-01 07:00:00',3)
ALTER TABLE dbo.TEST ADD "column2" FLOAT;
so the table looks like this:
now I want to fill column2 for 2:00 and 6:00 o clock with the values 20 and 21 but ignore value 25. What I have is
INSERT INTO dbo.TEST("column2")
SELECT
NewValues."column2"
FROM (
VALUES ('2018-04-01 02:00:00',20),
('2018-04-01 06:00:00',21),
('2019-10-05 20:30:00',25)
) AS NewValues(date_time,"column2")
INNER JOIN dbo.TEST
ON dbo.TEST.date_time = NewValues.date_time
WHERE dbo.TEST.date_time = NewValues.date_time
but this results in
what am I missing?
You want an update:
update t
set column2 = NewValues.column2
from dbo.TEST t left join
(values ('2018-04-01 02:00:00', 20),
('2018-04-01 06:00:00', 21),
('2019-10-05 20:30:00', 25)
) NewValues(date_time, column2)
ON t.date_time = NewValues.date_time;

Sql Server While Loop with Changing Condition

I have a User Table in my database that contains two fields
user_id
manager_id
I am trying to construct a query to list all of the manager_ids that are associated with a user_id in a hierarchical structure.
So if i give a user_id, i will get that users manager, followed by that persons manager all the way to the very top.
So far i have tried but it doesnt give what i need:
WITH cte(user_id, manager_id) as (
SELECT user_id, manager_id
FROM user
WHERE manager_id=#userid
UNION ALL
SELECT u.user_id, u.manager_id,
FROM user u
INNER JOIN cte c on e.manager_id = c.employee_id
)
INSERT INTO #tbl (manager_id)
select user_id, manager_id from cte;
If anyone can point me in the right direction that would be great.
I thought about a While loop but this may not be very efficient and im not too sure how to implement that.
OP asked for a while loop, and while (ha, pun) this may not be the best way... Ask and you shall receive. (:
Here is sample data I created (in the future, please provide this):
CREATE TABLE #temp (userID int, managerID int)
INSERT INTO #temp VALUES (1, 3)
INSERT INTO #temp VALUES (2, 3)
INSERT INTO #temp VALUES (3, 7)
INSERT INTO #temp VALUES (4, 6)
INSERT INTO #temp VALUES (5, 7)
INSERT INTO #temp VALUES (6, 9)
INSERT INTO #temp VALUES (7, 10)
INSERT INTO #temp VALUES (8, 10)
INSERT INTO #temp VALUES (9, 10)
INSERT INTO #temp VALUES (10, 12)
INSERT INTO #temp VALUES (11, 12)
INSERT INTO #temp VALUES (12, NULL)
While Loop:
CREATE TABLE #results (userID INT, managerID INT)
DECLARE #currentUser INT = 1 -- Would be your parameter!
DECLARE #maxUser INT
DECLARE #userManager INT
SELECT #maxUser = MAX(userID) FROM #temp
WHILE #currentUser <= #maxUser
BEGIN
SELECT #userManager = managerID FROM #temp WHERE userID = #currentUser
INSERT INTO #results VALUES (#currentUser, #userManager)
SET #currentUser = #userManager
END
SELECT * FROM #results
DROP TABLE #temp
DROP TABLE #results
Get rid of this column list in your CTE declaration that has nothing to do with the columns you are actually selecting in the CTE:
WITH cte(employee_id, name, reports_to_emp_no, job_number) as (
Just make it this:
WITH cte as (
I recommend recursive solution:
WITH Parent AS
(
SELECT * FROM user WHERE user_id=#userId
UNION ALL
SELECT T.* FROM user T
JOIN Parent P ON P.manager_id=T.user_id
)
SELECT * FROM Parent
To see demo, run following:
SELECT * INTO #t FROM (VALUES (1,NULL),(2,1),(3,2),(4,1)) T(user_id,manager_id);
DECLARE #userId int = 3;
WITH Parent AS
(
SELECT * FROM #t WHERE user_id=#userId
UNION ALL
SELECT T.* FROM #t T
JOIN Parent P ON P.manager_id=T.user_id
)
SELECT * FROM Parent

Find Groups that don't contain all records

I feel like I should be able to get this and I'm just having a brain fart. I've simplified the problem to the following example:
DECLARE #A TABLE (ID int);
DECLARE #B TABLE (GroupID char(1), ID int);
INSERT #A VALUES (1);
INSERT #A VALUES (2);
INSERT #A VALUES (3);
INSERT #B VALUES ('X', 1);
INSERT #B VALUES ('X', 2);
INSERT #B VALUES ('X', 3);
INSERT #B VALUES ('Y', 1);
INSERT #B VALUES ('Y', 2);
INSERT #B VALUES ('Z', 1);
INSERT #B VALUES ('Z', 2);
INSERT #B VALUES ('Z', 3);
INSERT #B VALUES ('Z', 4);
So table A contains a set of some records. Table B contains multiple copies of the set contained in A with Group IDs. But some of those groups may be missing one or more records of the set. I want to find the groups that are missing records. So in the above example, my results should be:
GroupID
-------
Y
But for some reason I just can't wrap my head around this, today. Any help would be appreciated.
Awesome use-case for relational division! (Here's a must-read blog post about it)
SELECT DISTINCT b1.GroupID
FROM #B b1
WHERE EXISTS (
SELECT 1
FROM #A a
WHERE NOT EXISTS (
SELECT 1
FROM #B b2
WHERE b1.GroupID = b2.GroupID
AND b2.ID = a.ID
)
);
How to read this?
I want all distinct GroupIDs in #B for which there is a record in #A for which there isn't a record in #B with the same #A.ID
In fact, this is the "remainder" of the relational division.
try this
SELECT GroupID ,COUNT(GroupID )
FROM #a INNER JOIN #b
ON #a.id=#b.id
GROUP BY GroupID
HAVING COUNT(GroupID )<(SELECT count(*) FROM #a)
This will give you all the combinations that are missing.
select FullList.*
from (select distinct a.ID,
b.GroupId
from #A a
cross join #B b) FullList
left join #B b
on FullList.ID = b.ID
and FullList.GroupID = b.GroupID
where b.ID is null
The answer to your question would just be the same but with the first line:
select distinct FullList.GroupID
This will give you all the combinations that are missing.
select FullList.*
from (select distinct a.ID,
b.GroupId
from #A a
cross join (select distinct db.GroupId from #B db) b
) as FullList
left join #B b
on FullList.ID = b.ID
and FullList.GroupID = b.GroupID
where b.ID is null
The answer to your question would just be the same but with the first line:
select distinct FullList.GroupID

Select query : from clause is having multple tables, but i want where clause to have condition on only two tables

For eg:
SELECT aa.name, aa.id
FROM ba_acct_memo aa, acct_mast bb
WHERE (aa.cod_acct_no=bb.cod_acct_no AND aa.flg_mnt_status='U'
and bb.flg_mnt_status='A')
gives 1 row(for eg)
but
SELECT aa.name, aa.id
FROM ba_acct_memo aa, acct_mast bb, college cc
WHERE (aa.cod_acct_no=bb.cod_acct_no AND aa.flg_mnt_status='U'
and bb.flg_mnt_status='A')
gives same result as in first query but giving it, as many number of rows which are there in college table.
But it should work just as like first query.
Can someone explain the weird behaviour of my query?
Following Steps will help you to understand (Inner) Join.
--Create Table 1 :
Create Table #Table1
(
Roll_No INT ,
Student_Name Varchar(50)
)
Go
--Create Table 2 :
Create Table #Table2
(
Roll_No INT,
Student_Address Varchar(200)
)
Go
--Create Table 3 :
Create Table #Table3
(
Roll_No INT,
Student_Contact_No Varchar(10)
)
Go
-- Insert Values into #Table1:
Insert into #Table1 Values ('1','John')
Insert into #Table1 Values ('2','Alex')
Insert into #Table1 Values ('3','Mike')
Insert into #Table1 Values ('4','Steve')
Insert into #Table1 Values ('5','Jack')
Insert into #Table1 Values ('6','Vicky')
Insert into #Table1 Values ('7','Sid')
Insert into #Table1 Values ('8','Tom')
-- Insert Values into #Table2:
Insert into #Table2 Values ('1','1st Street')
Insert into #Table2 Values ('2','2rd Street')
Insert into #Table2 Values ('3','3rd Street')
Insert into #Table2 Values ('4','4th Street')
Insert into #Table2 Values ('5','5th Street')
Insert into #Table2 Values ('6','6th Street')
Insert into #Table2 Values ('7','7th Street')
Insert into #Table2 Values ('8','8th Street')
-- Insert Values into #Table3:
Insert into #Table3 Values ('1','123-123')
Insert into #Table3 Values ('2','123-111')
Insert into #Table3 Values ('3','123-122')
Insert into #Table3 Values ('4','123-125')
Insert into #Table3 Values ('5','123-126')
Insert into #Table3 Values ('6','123-116')
Insert into #Table3 Values ('7','123-145')
Insert into #Table3 Values ('8','123-132')
--View Data :
Select * from #Table1
Select * from #Table2
Select * from #Table3
-- First Query : (With Out Third Table) :
Select A.Roll_No,A.Student_Name,B.Student_Address from #Table1 A, #Table2 B
Where a.Roll_No = B.Roll_No
and a.Roll_No = 1
--It will Retrun One Record. If you add third table in this query with out join with any other tables ( Table 1 and Table 2 )
-- Secord Query :
Select A.Roll_No,A.Student_Name,B.Student_Address from #Table1 A, #Table2 B , #Table3 C
Where a.Roll_No = B.Roll_No
and a.Roll_No = 1
--It will return 8 Same Records. (Because Table 3 having 8 Records)
--You can understand when execute why it is return 8 records.
-- Third Query :
Select * from #Table1 A, #Table2 B , #Table3 C
Where a.Roll_No = B.Roll_No
and a.Roll_No = 1
--Delete some records from #Table 3 :
Delete #Table3 Where Roll_No > 5
--Execute again Third Query :
-- Third Query :
Select * from #Table1 A, #Table2 B , #Table3 C
Where a.Roll_No = B.Roll_No
and a.Roll_No = 1
--Clean Up:
Drop table #Table1
Drop table #Table2
Drop table #Table3

SQL Server Simple Group by query

I have a simple problem , Although i believe its simple , am not able to figure out the same.
Consider i have the below table with exactly same data as given below :
CREATE TABLE #temp
(
link varchar(255),
number INT,
fname varchar(255)
)
insert into #temp VALUES ('abc',1,'f1')
insert into #temp VALUES ('abc',2,'f2')
insert into #temp VALUES ('abc',3,'f3')
insert into #temp VALUES ('abc',4,'f6')
insert into #temp VALUES ('abc',10,'f100')
insert into #temp VALUES ('abe',-1,'f0')
insert into #temp VALUES ('abe',1,'f1')
insert into #temp VALUES ('abe',2,'f2')
insert into #temp VALUES ('abe',3,'f3')
insert into #temp VALUES ('abe',4,'f6')
insert into #temp VALUES ('abe',20,'f200')
insert into #temp VALUES ('cbe',-1,'f0')
insert into #temp VALUES ('cbe',1,'f1')
insert into #temp VALUES ('cbe',2,'f2')
insert into #temp VALUES ('cbe',3,'f3')
Now for a given link , i need to get the max 'number' and the corresponding 'fname' which has the max 'number' for the given 'link'.
1)Ex : if link is 'abc' , output should be
abc, 10, f100
2)Ex : if link if 'abe' , Output should be
abe, 20, f200
3)Now link can be also given as a pattern , like (link like 'ab%') , so output should be
abc, 10, f100
abe, 20, f200
4)if (link like 'cb%') , so output should be
cbe, 3, f3
Any help in writing this group by query. I have a solution using CAST and string concat like below , but that seems to be in-efficient.
select link,number,fname from #temp
where link like 'ab%' and link+'_'+CAST(number AS varchar(255))
in (select link+'_'+CAST(MAX(number) AS varchar(255)) from #temp
group by link)
Thanks..
Using a self join:
SELECT x.link,
x.number,
x.fname
FROM #temp x
JOIN (SELECT t.link,
MAX(t.number) AS max_number
FROM #temp t
GROUP BY t.link) y ON y.link = x.link
AND y.max_number = x.number
Using a CTE and ROW_NUMBER (SQL Server 2005+):
WITH cte AS (
SELECT x.link,
x.number,
x.fname,
ROW_NUMBER() OVER(PARTITION BY x.link
ORDER BY x.number DESC) rank
FROM #temp x)
SELECT c.link,
c.number,
c.fname
FROM cte c
WHERE c.rank = 1