SQL Insert values by join - sql

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;

Related

Find new dates for list of deals

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;

How to insert into a table with a unique identity INT column as primary key

To insert into a table with the next integer ID value, would it look something like this?
DECLARE #RoomID INT
SELECT #RoomID = (SELECT count(*) FROM [dbo].[Rooms])
SELECT #RoomID = SELECT #RoomID + 1
INSERT INTO [dbo].[Rooms]
([RoomID],
[RoomType],
[Description],
[DateCreated],
[IsActive])
VALUES
(#RoomID,
2,
N'Room Description X',
CONVERT(DateTime2, getdate()),
1)
If you want to force a specific number into a column that is an identity column you have to use the command SET IDENTITY_INSERT table_name OFF and turn it back on after your done.
https://learn.microsoft.com/en-us/sql/t-sql/statements/set-identity-insert-transact-sql
If you just want to insert data into the table, you skip the column and SQL Server will insert it for you.
INSERT INTO [dbo].[Rooms]
(
[RoomType],
[Description],
[DateCreated],
[IsActive])
VALUES
(
2,
N'Room Description X',
CONVERT(DateTime2, getdate()),
1)

I need to migrate data from one old table to a new table by storing appropriate CityId instead CityName

I'm migrating data from one table to another table in SQL Server, In this process what I need to do is "I have 10 columns in old table one column is 'CityName' which is varchar and in the new table, I have a column 'CityId' which is an integer. And I have other table which has data about city id and names. I need store the appropriate cityId in new table instead of CityName. Please help me. Thanks in advance.
You'll need to join the source table to the CityName field in the city information table:
INSERT INTO dbo.Destination (CityID, OtherStuff)
SELECT t1.CityID, t2.OtherStuff
FROM CityInformationTable t1
INNER JOIN SourceTable t2
ON t1.CityName = t2.CityName
Below should give you an idea, you need to inner join to your look up table to achieve this.
declare #t_cities table (Id int, City nvarchar(20))
insert into #t_cities
(Id, City)
values
(1, 'London'),
(2, 'Dublin'),
(3, 'Paris'),
(4, 'Berlin')
declare #t table (City nvarchar(20), SomeColumn nvarchar(10))
insert into #t
values
('London', 'AaaLon'),
('Paris', 'BeePar'),
('Berlin', 'CeeBer'),
('London', 'DeeLon'),
('Dublin', 'EeeDub')
declare #finalTable table (Id int, SomeColumn nvarchar(10))
insert into #finalTable
select c.Id, t.SomeColumn
from #t t
join #t_cities c on c.City = t.City
select * from #finalTable
Output:
Id SomeColumn
1 AaaLon
3 BeePar
4 CeeBer
1 DeeLon
2 EeeDub

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

project a sparse result at some level

I don't really know what to call this but it's not that hard to explain
Basically what I have is a result like this
Similarity ColumnA ColumnB ColumnC
1 SomeValue NULL SomeValue
2 NULL SomeB NULL
3 SomeValue NULL SomeC
4 SomeA NULL NULL
This result is created by matching a set of strings against another table. Each string also contains some values for these ColumnA..C which are the values I wan't to aggregate in some way.
Something like min/max works very well but I can't figure out how to get it to account for the highest similarity not just the min/max value. I don't really want the min/max, I want the first non-null value with the highest similarity.
Ideally the result would look like this
ColumnA ColumnB ColumnC
SomeA SomeB SomeC
I'd like be able to efficiently join in the temporary result to compute the rest and I've been exploring different options. Something which I've been considering is creating a SQL Server CLR aggregate the yields the "first" non-null value but I'm unsure if there's even such a thing as a first or last when running an aggregate on a result.
Okay, so I figured it out, I originally had trouble with the UPDATE FROM and JOIN not playing well together. I was counting on that the UPDATE would just occur multiple times and that would give me the correct results, however, there's no such guarantee from SQL Server (it's actually undefined behavior and alltough it appeared to work we'll have none of that) but since you can run UPDATE against a CTE I combined that with the OUTER APPLY to select the exactly 1 row to complement a missing value if possible.
Here's the whole thing with test data as well.
DECLARE #cost TABLE (
make nvarchar(100) not null,
model nvarchar(100),
a numeric(18,2),
b numeric(18,2)
);
INSERT #cost VALUES ('a%', null, 100, 2);
INSERT #cost VALUES ('a%', 'a%', 149, null);
INSERT #cost VALUES ('a%', 'ab', 349, null);
INSERT #cost VALUES ('b', null, null, 2.5);
INSERT #cost VALUES ('b', 'b%', 249, null);
INSERT #cost VALUES ('b', 'b', null, 3);
DECLARE #unit TABLE (
id int,
make nvarchar(100) not null,
model nvarchar(100)
);
INSERT #unit VALUES (1, 'a', null);
INSERT #unit VALUES (2, 'a', 'a');
INSERT #unit VALUES (3, 'a', 'ab');
INSERT #unit VALUES (4, 'b', null);
INSERT #unit VALUES (5, 'b', 'b');
DECLARE #tmp TABLE (
id int,
specificity int,
a numeric(18,2),
b numeric(18,2),
primary key(id, specificity)
);
INSERT #tmp
OUTPUT inserted.* --FOR DEBUGGING
SELECT
unit.id
, ROW_NUMBER() OVER (
PARTITION BY unit.id
ORDER BY cost.make DESC, cost.model DESC
) AS specificity
, cost.a
, cost.b
FROM #unit unit
INNER JOIN #cost cost ON unit.make LIKE cost.make
AND (cost.model IS NULL OR unit.model LIKE cost.model)
;
--fix the holes
WITH tmp AS (
SELECT *
FROM #tmp
WHERE specificity = 1
AND (a IS NULL OR b IS NULL) --where necessary
)
UPDATE tmp
SET
tmp.a = COALESCE(tmp.a, a.a)
, tmp.b = COALESCE(tmp.b, b.b)
OUTPUT inserted.* --FOR DEBUGGING
FROM tmp
OUTER APPLY (
SELECT TOP 1 a
FROM #tmp a
WHERE a.id = tmp.id
AND a.specificity > 1
AND a.a IS NOT NULL
ORDER BY a.specificity
) a
OUTER APPLY (
SELECT TOP 1 b
FROM #tmp b
WHERE b.id = tmp.id
AND b.specificity > 1
AND b.b IS NOT NULL
ORDER BY b.specificity
) b
;