INSERT INTO table from 2 unrelated tables - sql-server

Not sure how to achieve the result, need your help
Source A:
SELECT SourceAID
FROM [dbo].[SourceA]
Source B:
SELECT SourceBID
FROM [dbo].[SourceB]
Result table (select example):
SELECT SourceAID
,SourceBID
,Value
FROM [dbo].[Result]
Idea of insert: For each SourceAID, i need to insert records with all SourceBID. There is no any reference between these 2 tables.
Idea by hand looks like this:
INSERT INTO [dbo].[Result] ([SourceAID], [SourceBID], [Value])
VALUES ('AID_1', 'BID_1', NULL),
('AID_1', 'BID_2', NULL),
('AID_1', 'BID_3', NULL),
('AID_2', 'BID_1', NULL),
('AID_2', 'BID_2', NULL),
('AID_2', 'BID_3', NULL)
and so on

As #Larnu said.
Use some following code:
INSERT INTO [dbo].[Result] ([SourceAID], [SourceBID], [Value])
SELECT
SA.SourceAID,
SB.SourceBID,
NULL
FROM
[dbo].[SourceA] AS SA
CROSS JOIN [dbo].[SourceB] AS SB

The other way is using subquery
INSERT INTO [dbo].[Result] ([SourceAID], [SourceBID], [Value])
SELECT SA.SourceAID,SB.SourceBID,NULL
(SELECT 1 AS ID ,SA.SourceAID FROM [dbo].[SourceA]) SA
join
(SELECT 1 AS ID ,SA.SourceBID FROM [dbo].[SourceB]) SB
on SA.ID=SB.ID

Related

Show all and only rows in table 1 not in table 2 (using multiple columns)

I have one table (Table1) that has several columns used in combination: Name, TestName, DevName, Dept. When each of these 4 columns have values, the record is inserted into Table2. I need to confirm that all of the records with existing values in each of these fields within Table1 were correctly copied into Table 2.
I have created a query for it:
SELECT DISTINCT wr.Name,wr.TestName, wr.DEVName ,wr.Dept
FROM table2 wr
where NOT EXISTS (
SELECT NULL
FROM TABLE1 ym
WHERE ym.Name = wr.Name
AND ym.TestName = wr. TestName
AND ym.DEVName = wr.DEVName
AND ym. Dept = wr. Dept
)
My counts are not adding up, so I believe that this is incorrect. Can you advise me on the best way to write this query for my needs?
You can use the EXCEPT set operator for this one if the table definitions are identical.
SELECT DISTINCT ym.Name, ym.TestName, ym.DEVName, ym.Dept
FROM table1 ym
EXCEPT
SELECT DISTINCT wr.Name, wr.TestName, wr.DEVName, wr.Dept
FROM table2 wr
This returns distinct rows from the first table where there is not a match in the second table. Read more about EXCEPT and INTERSECT here: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql?view=sql-server-2017
Your query should do the job. It checks anything that are in Table1, but not Table2
SELECT ym.Name, ym.TestName, ym.DEVName, ym.Dept
FROM Table1 ym
WHERE NOT EXISTS (
SELECT 1
FROM table2
WHERE ym.Name = Name AND ym.TestName = TestName AND ym.DEVName = DEVName AND ym. Dept = Dept
)
If the structure of both tables are the same, EXCEPT is probably simpler.
IF OBJECT_ID(N'tempdb..#table1') IS NOT NULL drop table #table1
IF OBJECT_ID(N'tempdb..#table2') IS NOT NULL drop table #table2
create table #table1 (id int, value varchar(10))
create table #table2 (id int)
insert into #table1(id, value) VALUES (1,'value1'), (2,'value2'), (3,'value3')
--test here. Comment next line
insert into #table2(id) VALUES (1) --Comment/Uncomment
select * from #table1
select * from #table2
select #table1.*
from #table1
left JOIN #table2 on
#table1.id = #table2.id
where (#table2.id is not null or not exists (select * from #table2))

SQL Function to return sequential id's

Consider this simple INSERT
INSERT INTO Assignment (CustomerId,UserId)
SELECT CustomerId,123 FROM Customers
That will obviously assign UserId=123 to all customers.
What I need to do is assign them to 3 userId's sequentially, so 3 users get one third of the accounts equally.
INSERT INTO Assignment (CustomerId,UserId)
SELECT CustomerId,fnGetNextId() FROM Customers
Could I create a function to return sequentially from a list of 3 ID's?, i.e. each time the function is called it returns the next one in the list?
Thanks
Could I create a function to return sequentially from a list of 3 ID's?,
If you create a SEQUENCE, then you can assign incremental numbers with the NEXT VALUE FOR (Transact-SQL) expression.
This is a strange requirement, but the modulus operator (%) should help you out without the need for functions, sequences, or altering your database structure. This assumes that the IDs are integers. If they're not, you can use ROW_NUMBER or a number of other tactics to get a distinct number value for each customer.
Obviously, you would replace the SELECT statement with an INSERT once you're satisfied with the code, but it's good practice to always select when developing before inserting.
SETUP WITH SAMPLE DATA:
DECLARE #Users TABLE (ID int, [Name] varchar(50))
DECLARE #Customers TABLE (ID int, [Name] varchar(50))
DECLARE #Assignment TABLE (CustomerID int, UserID int)
INSERT INTO #Customers
VALUES
(1, 'Joe'),
(2, 'Jane'),
(3, 'Jon'),
(4, 'Jake'),
(5, 'Jerry'),
(6, 'Jesus')
INSERT INTO #Users
VALUES
(1, 'Ted'),
(2, 'Ned'),
(3, 'Fred')
QUERY:
SELECT C.Name AS [CustomerName], U.Name AS [UserName]
FROM #Customers C
JOIN #Users U
ON
CASE WHEN C.ID % 3 = 0 THEN 1
WHEN C.ID % 3 = 1 THEN 2
WHEN C.ID % 3 = 2 THEN 3
END = U.ID
You would change the THEN 1 to whatever your first UserID is, THEN 2 with the second UserID, and THEN 3 with the third UserID. If you end up with another user and want to split the customers 4 ways, you would do replace the CASE statement with the following:
CASE WHEN C.ID % 4 = 0 THEN 1
WHEN C.ID % 4 = 1 THEN 2
WHEN C.ID % 4 = 2 THEN 3
WHEN C.ID % 4 = 3 THEN 4
END = U.ID
OUTPUT:
CustomerName UserName
-------------------------------------------------- --------------------------------------------------
Joe Ned
Jane Fred
Jon Ted
Jake Ned
Jerry Fred
Jesus Ted
(6 row(s) affected)
Lastly, you will want to select the IDs for your actual insert, but I selected the names so the results are easier to understand. Please let me know if this needs clarification.
Here's one way to produce Assignment as an automatically rebalancing view:
CREATE VIEW dbo.Assignment WITH SCHEMABINDING AS
WITH SeqUsers AS (
SELECT UserID, ROW_NUMBER() OVER (ORDER BY UserID) - 1 AS _ord
FROM dbo.Users
), SeqCustomers AS (
SELECT CustomerID, ROW_NUMBER() OVER (ORDER BY CustomerID) - 1 AS _ord
FROM dbo.Customers
)
-- INSERT Assignment(CustomerID, UserID)
SELECT SeqCustomers.CustomerID, SeqUsers.UserID
FROM SeqUsers
JOIN SeqCustomers ON SeqUsers._ord = SeqCustomers._ord % (SELECT COUNT(*) FROM SeqUsers)
;
This shifts assignments around if you insert a new user, which could be quite undesirable, and it's also not efficient if you had to JOIN on it. You can easily repurpose the query it contains for one-time inserts (the commented-out INSERT). The key technique there is joining on ROW_NUMBER()s.

CTE to pull entire tree from arbitrary entry

I'm trying to build a CTE which will pull back all records which are related to a given, arbitrary record in the database.
Create table Requests (
Id bigint,
OriginalId bigint NULL,
FollowupId bigint NULL
)
insert into Requests VALUES (1, null, 3)
insert into Requests VALUES (2, 1, 8)
insert into Requests VALUES (3, 1, 4)
insert into Requests VALUES (4, 3, null)
insert into Requests VALUES (5, null, null)
insert into Requests VALUES (6, null, 7)
insert into Requests VALUES (7, 6, null)
insert into Requests VALUES (8, 2, null)
OriginalId is always the Id of a previous record (or null). FollowupId points to the most recent followup record (which, in turn, points back via OriginalId) and can probably be ignored, but it's there if it's helpful.
I can easily pull back either all ancestors or all descendants of a given record using the following CTE
;With TransactionList (Id, originalId, followupId, Steps)
AS
(
Select Id, originalId, followupId, 0 as Steps from requests where Id = #startId
union all
select reqs.Id, reqs.originalId, reqs.followupId, Steps + 1 from requests reqs
inner join TransactionList tl on tl.Id = reqs.originalId --or tl.originalId = reqs.Id
)
SELECT Id from TransactionList
However, if I use both where clauses, I run into recursion, hit the recursion limit, and it bombs out. Even combining both sets, I don't get the entire tree - just one branch from it.
I don't care about anything other than the list of Ids. They don't need to be sorted, or to display their relationship or anything. Doesn't hurt, but not necessary. But I need every Id in a given tree to pull back the same list when it's passed as #startId.
As an example of what I'd like to see, this is what the output should be when #startId is set to any value 1-4 or 8:
1
2
3
4
8
And for either 6 or 7, I get back both 6 and 7.
You can just create 2 CTE's.
The first CTE will get the Root of the hierarchy, and the second will use the Root ID to get the descendants of the Root.
;WITH cteRoot AS (
SELECT *, 0 [Level]
FROM Requests
WHERE Id = #startId
UNION ALL
SELECT r.*, [Level] + 1
FROM Requests r
JOIN cteRoot cte ON r.Id = cte.OriginalID
),
cteDesc AS (
SELECT *
FROM cteRoot
WHERE OriginalId IS NULL
UNION ALL
SELECT r.*, [Level] + 1
FROM Requests r
JOIN cteDesc cte ON r.OriginalId = cte.Id
)
SELECT * FROM cteDesc
SQL Fiddle

Multiple Insert for each of the Account IDs?

How do I effectively insert multiple rows without using loop for all of the Account-ID values?
INSERT INTO Table1
(AccountID, ShowColumns, GroupColumns, AvgColumnsFlag)
VALUES
(1, 'foo1', 'foo2', 'foo3')
(1, 'abc1', 'abc2', 'abc3')
(1, 'xyz1', 'xyz1', 'xyz1')
In this case, I have over 20,000 account ids. I can use one other table with unique account ID and do some kind of joining to get that. Then use it to in place of the displayed example Account-ID of "1".
I don't know how you guys do with multiple inserts for each Account-ID.
Thanks...
[Edit]
I found a way to insert using data from other table recently but unfortunately I can only insert 1 row, not multiple rows. :-( See code below... Is it possible to consolidate 3 of them into 1 instead?
INSERT INTO tblDealerSavedDataMyInventorySavedBuilds
(AccountId, LoadDefault, BuildName, ColumnShowAndSortOrderValues, ColumnGroupByValues, ColumnSortAverageValues)
SELECT DISTINCT tblaAccounts.AccountID, 0, 'My Inventory by Count', 'ImportStatus|StockNumber|Vin|Year|Make ASC|Model ASC|Trim|Mileage|PurchasePrice|StockDate|RepairCost|TotalCost|DaysInInventory|InventoryTrackerLocation|Category', 'Make|Model', 'MyInventoryCount-SortOrderByCount'
FROM tblaAccounts
ORDER BY tblaAccounts.AccountID ASC
INSERT INTO tblDealerSavedDataMyInventorySavedBuilds
(AccountId, LoadDefault, BuildName, ColumnShowAndSortOrderValues, ColumnGroupByValues, ColumnSortAverageValues)
SELECT DISTINCT tblaAccounts.AccountID, 0, 'My Inventory by Make', 'ImportStatus|StockNumber|Vin|Year|Make ASC|Model ASC|Trim|Mileage|PurchasePrice|StockDate|RepairCost|TotalCost|DaysInInventory|InventoryTrackerLocation|Category', 'Make|Model', 'MyInventoryCount-SortOrderByMake'
FROM tblaAccounts
ORDER BY tblaAccounts.AccountID ASC
INSERT INTO tblDealerSavedDataMyInventorySavedBuilds
(AccountId, LoadDefault, BuildName, ColumnShowAndSortOrderValues, ColumnGroupByValues, ColumnSortAverageValues)
SELECT DISTINCT tblaAccounts.AccountID, 0, 'My Inventory by Purchase Price', 'ImportStatus|StockNumber|Vin|Year|Make ASC|Model ASC|Trim|Mileage|PurchasePrice|StockDate|RepairCost|TotalCost|DaysInInventory|InventoryTrackerLocation|Category', 'Make|Model', 'MyInventoryCount-SortOrderByCost'
FROM tblaAccounts
ORDER BY tblaAccounts.AccountID ASC
First insert into #SourceTable all your values.
Then use this statement:
INSERT INTO Table1
SELECT *
FROM #SourceTable
It may look the same, but it's different, since you are actually addressing the table once, instead of 20,000 times..
You can also do it this way:
INSERT INTO Table1
SELECT 1, 'foo1', 'foo2', 'f003'
UNION ALL
SELECT 2, 'abc11', 'abc2', 'abc3'
UNION ALL
...
To insert multiple rows with hard-coded values use
insert into table (col1, col2, col3)
select 1, 'foo1', 'foo2', 'f003'
union all
select 2, 'abc11', 'abc2', 'abc3'
etc.
To insert from existing data
insert into table (col1, col2, col3)
select srccol1, srccol22, srccol33
from TableOrView

Sorting SQL table

can anyone help me with T-SQL to sort this table
ID Comment ParentId
-- ------- --------
3 t1 NULL
4 t2 NULL
5 t1_1 3
6 t2_1 4
7 t1_1_1 5
to look like this
ID Comment ParentId
-- ------- --------
3 t1 NULL
5 t1_1 3
7 t1_1_1 5
4 t2 NULL
6 t2_1 4
Kind regards,
Lennart
try this:
DECLARE #YourTable table (id int, Comment varchar(10), parentID int)
INSERT INTO #YourTable VALUES (3, 't1' , NULL)
INSERT INTO #YourTable VALUES (4, 't2' , NULL)
INSERT INTO #YourTable VALUES (5, 't1_1' , 3)
INSERT INTO #YourTable VALUES (6, 't2_1' , 4)
INSERT INTO #YourTable VALUES (7, 't1_1_1', 5)
;with c as
(
SELECT id, comment, parentid, CONVERT(varchar(8000),RIGHT('0000000000'+CONVERT(varchar(10),id),10)) as SortBy
from #YourTable
where parentID IS NULL
UNION ALL
SELECT y.id, y.comment, y.parentid, LEFT(c.SortBy+CONVERT(varchar(8000),RIGHT('0000000000'+CONVERT(varchar(10),y.id),10)),8000) AS SortBy
FROM c
INNER JOIN #YourTable y ON c.ID=y.PArentID
)
select * from C ORDER BY SortBy
EDIT
here is output
id comment parentid SortBy
----------- ---------- ----------- ---------------------------------
3 t1 NULL 0000000003
5 t1_1 3 00000000030000000005
7 t1_1_1 5 000000000300000000050000000007
4 t2 NULL 0000000004
6 t2_1 4 00000000040000000006
(5 row(s) affected)
humm order by?
http://t-sql.pro/t-sql/ORDER-BY.aspx
SELECT ID, Comment, ParentId
FROM TestTable
ORDER BY Comment, ParentId asc
This sounds very much like a homework question, but here's some hints on where to go with this:
You'll want to do a quick google or StackOverflow search for the ORDER BY clause to be able to get a set of results ordered by the column you want to use (i.e. the 'Comment' column).
Once you've got that, you can start writing a SQL statement to order your results.
If you need to then place re-order the actual table (and not just get the results in a specific order), you'll need to look up using temporary tables (try searching for 'DECLARE TABLE'). Much like any temp swap, you can place the results you have in a temporary place, delete the old data, and then replace the table contents with the temporary data you have, but this time in the order you want.
But just ordering by Comment will give you that? Or have I missed the point?!
declare #table table
(
Comment varchar(10)
)
insert into #table (Comment) values ('t1')
insert into #table (Comment) values ('t2')
insert into #table (Comment) values ('t1_1')
insert into #table (Comment) values ('t2_1')
insert into #table (Comment) values ('t1_1_1')
select * from #table order by comment

Resources