I have two tables, tblName and tblCode.
tblName:
CREATE TABLE [dbo].[TblName]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
CONSTRAINT [PK_TblName]
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY]
tblCode:
CREATE TABLE [dbo].[tblCode]
(
[NameId] [int] NULL,
[Code] [varchar](50) NULL,
[Value] [varchar](50) NULL
) ON [PRIMARY]
Code:
INSERT INTO [dbo].[TblName]
([Name])
VALUES
('Rahul'),
('Rohit'),
('John'),
('David'),
('Stephen')
GO
INSERT INTO [dbo].[tblCode] ([NameId], [Code], [Value])
VALUES (1, 'DEL', 'Delivery'),
(1, 'DEL', 'Deployment'),
(2, 'REL', 'Release Management'),
(3, 'REL', 'Release Management'),
(4, 'TEST', 'Testing'),
(4, 'TEST', 'Final Testing')
I am trying to write a query to get all Names which are in tblCode with the Code and Value. For example I have NameId 1 present in tblCode with Code 'DEL' and Value as 'Delivery' and 'Deployment'. Similarly I have NameId 2,3 and 4 in tblCode with same or different Code and Value. So I am trying to get output in such a way if same name with same code is present in tblCode then it should come row with Name and Comma separated values as shown in below desired output.
This is they query I am using but its not giving the output I am looking for.
SELECT
N.Name,
CASE
WHEN C.Code = 'DEL'
THEN C.Value
ELSE ''
END As 'CodeValue'
FROM
TblName N
INNER JOIN
tblCode C ON N.Id = C.NameId
WHERE
C.NameId = 1 AND C.Code IN ('DEL', 'REL', 'TEST')
http://sqlfiddle.com/#!6/bdca78/11/0
CREATE TABLE tblName (id INTEGER, name VARCHAR(255));
INSERT INTO tblName VALUES(1, 'Rahul');
INSERT INTO tblName VALUES(2, 'Rohit');
INSERT INTO tblName VALUES(3, 'John');
INSERT INTO tblName VALUES(4, 'David');
INSERT INTO tblName VALUES(5, 'Steven');
CREATE TABLE tblCode(nameId INTEGER, code VARCHAR(255), value VARCHAR(255));
INSERT INTO tblCode VALUES(1, 'DEL', 'Delivery');
INSERT INTO tblCode VALUES(1, 'DEL', 'Development');
INSERT INTO tblCode VALUES(2, 'REL', 'Release Management');
INSERT INTO tblCode VALUES(3, 'REL', 'Release Management');
INSERT INTO tblCode VALUES(4, 'TEST', 'Testing');
INSERT INTO tblCode VALUES(4, 'TEST', 'Final Testing');
SELECT name,
codeValue
FROM
(SELECT tblName.name AS name,
STUFF((SELECT ',' + tblCode.value
FROM tblCode
WHERE tblCode.nameId = tblName.id
FOR XML PATH('')), 1 ,1, '') AS codeValue
FROM tblName) inline_view
WHERE codeValue IS NOT NULL;
Edit
ZoharPeled's solution is correct. This solution returns the name and a comma separated list of value and does not consider the code.
Zohar aggregates the list of value per code, which I think is what's required. OP, if the objective is to aggregate per name per code, including code in the output would make the result set more meaningful.
The following links show the difference, first is my SQL statement, then Zohar's.
My SQL: http://sqlfiddle.com/#!6/94fd0/1/0
Zohar's SQL: http://sqlfiddle.com/#!6/94fd0/2/0
Here is one way to do it:
;WITH CTE AS
(
SELECT DISTINCT
[NameId]
,[Code]
,(
SELECT STUFF(
(SELECT ',' + Value
FROM dbo.tblCode t1
WHERE t0.Code = t1.Code
AND t0.NameId = t1.NameId
FOR XML PATH(''))
, 1, 1, '')
) AS CodeValue
FROM dbo.tblCode t0
)
SELECT Name, CodeValue
FROM tblName
INNER JOIN CTE ON Id = CTE.NameId
ORDER BY Id
Results:
Name CodeValue
Rahul Delivery,Deployment
Rohit Release Management
John Release Management
David Testing,Final Testing
Read this SO post for an explanation on how to use STUFF and FOR XML to create a concatenated string from multiple rows.
You can see a live demo on rextester.
Related
I need your help building a sql query using vb6 and a access db. Here is the scenario: 2 Tables, Give and Have
Tb1 fields Id, Name, Amount
Tb2 Id, Name, Amount
I need to have the total amount for each name in both tables so to have total Give column and total have column but my query doesn't function
Select tb1.id,tb1.name,sum(tb1.amount) as TG, tb2.id,tb2.name,sum(tb2.amount) as TH
from tb1 inner join
tb2
on tb1.id=tb2.id
group by... Etc
If i have 10 records where id = 1 on tb1 and 3 records on tb 2 the total amount on tb2 is wrong (it repeats the sum on tb2 for each record on tb1)
I have tried also using Union obtaining a correct result in row but i should want to obtain something like
Id Name Have Give
1 John Doe 200,00 76,00
I hope to explain better by pics
Triyng #Parfait suggest, the result obtained is very similar to the query I wrote previously.
Thanks in advance for your help
Consider joining aggregates of both tables separately by id:
Aggregate Queries (save as stored Access queries)
SELECT tb1.idF
, tb1.[name]
, SUM(tb1.Give) AS TG
FROM tblGive tb1
GROUP BY tb1.idF
, tb1.[name]
SELECT tb2.IDB
, tb2.[name]
, SUM(tb2.Have) AS TH
FROM tblHave tb2
GROUP BY tb2.IDB
, tb2.name
Final Query (running Full Join Query to return all distinct names in either tables)
SELECT NZ(agg1.idF, agg2.idB) AS [id]
, NZ(agg1.name, agg2.name) AS [name]
, NZ(agg2.TH, 0) AS [Have]
, NZ(agg1.TG, 0) AS [Give]
FROM tblGiveAgg agg1
LEFT JOIN tblHaveAgg agg2
ON agg1.idF = agg2.idB
UNION
SELECT NZ(agg1.idF, agg2.idB) AS [id]
, NZ(agg1.name, agg2.name) AS [name]
, NZ(agg2.TH, 0) AS [Have]
, NZ(agg1.TG, 0) AS [Give]
FROM tblGiveAgg agg1
RIGHT JOIN tblHaveAgg agg2
ON agg1.idF = agg2.idB;
To demonstrate with below data
CREATE TABLE tblGive (
ID AUTOINCREMENT,
IdF INTEGER,
[Name] TEXT(10),
Give INTEGER
);
INSERT INTO tblGive (IdF, [Name], [Give]) VALUES (1, 'JOHN', 37);
INSERT INTO tblGive (IdF, [Name], [Give]) VALUES (2, 'ANNA', 10);
INSERT INTO tblGive (IdF, [Name], [Give]) VALUES (3, 'BILL', -37);
INSERT INTO tblGive (IdF, [Name], [Give]) VALUES (2, 'ANNA', 116);
INSERT INTO tblGive (IdF, [Name], [Give]) VALUES (1, 'JOHN', 120);
CREATE TABLE tblHave (
ID AUTOINCREMENT,
IDB INTEGER,
[Name] TEXT(10),
Have INTEGER
);
INSERT INTO tblHave (IDB, [Name], [Have]) VALUES (1, 'JOHN', 200);
INSERT INTO tblHave (IDB, [Name], [Have]) VALUES (2, 'ANNA', 400);
INSERT INTO tblHave (IDB, [Name], [Have]) VALUES (3, 'BILL', 150);
INSERT INTO tblHave (IDB, [Name], [Have]) VALUES (1, 'JOHN', 25);
INSERT INTO tblHave (IDB, [Name], [Have]) VALUES (1, 'JOHN', 70);
Final Full Join Query returns following result:
Try using union all and then aggregating:
Select id, name, sum(tg) as tg, sum(th) as th
from (select id, name, amount as tg, 0 as th from tb1
union all
select id, name, 0, amount from tbl2
) as t
group by id, name;
I'm not sure if all versions of MS Access support union all in the from clause like that. If not, that piece needs to be encapsulated in a view.
Using this DDL
CREATE TABLE tb1 (
ID AUTOINCREMENT,
IdF INTEGER,
[Name] TEXT(10),
Give INTEGER
);
INSERT INTO tb1 (IdF, [Name], [Give]) VALUES (1, 'JOHN', 37);
INSERT INTO tb1 (IdF, [Name], [Give]) VALUES (2, 'ANNA', 10);
INSERT INTO tb1 (IdF, [Name], [Give]) VALUES (3, 'BILL', -37);
INSERT INTO tb1 (IdF, [Name], [Give]) VALUES (2, 'ANNA', 116);
INSERT INTO tb1 (IdF, [Name], [Give]) VALUES (1, 'JOHN', 120);
CREATE TABLE tb2 (
ID AUTOINCREMENT,
IDB INTEGER,
[Name] TEXT(10),
Have INTEGER
);
INSERT INTO tb2 (IDB, [Name], [Have]) VALUES (1, 'JOHN', 200);
INSERT INTO tb2 (IDB, [Name], [Have]) VALUES (2, 'ANNA', 400);
INSERT INTO tb2 (IDB, [Name], [Have]) VALUES (3, 'BILL', 150);
INSERT INTO tb2 (IDB, [Name], [Have]) VALUES (1, 'JOHN', 25);
INSERT INTO tb2 (IDB, [Name], [Have]) VALUES (1, 'JOHN', 70);
This UNION ALL query works
SELECT Name
, SUM(Give) AS TotalGive
, SUM(Have) AS YotalHave
FROM (
SELECT Name, Give, 0 AS Have
FROM tb1
UNION ALL
SELECT Name, 0 AS Give, Have
FROM tb2
) AS t
GROUP BY Name;
I have the following table and data:
CREATE TABLE TEST_TABLE (
ID NUMBER(6) NOT NULL,
COMMON_SEQ NUMBER(22),
NAME VARCHAR(20),
CONSTRAINT PK_CONST PRIMARY KEY (ID)
);
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1001, NULL, 'Michelle');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1002, NULL, 'Tiberius');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1003, NULL, 'Marigold');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1004, 999, 'Richmond');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1005, 999, 'Marianne');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1006, NULL, 'Valentin');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1007, 888, 'Juliette');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1008, NULL, 'Lawrence');
Some records in this table are related to each other by the common value of COMMON_SEQ (for example COMMON_SEQ of 999 relates Richmond and Marianne).
How can I select all names based on given ID as an input?
I tried joining table to itself (works ok when COMMON_SEQ is null). This example returns Michelle record:
SELECT T.ID, T.COMMON_SEQ,T.NAME
FROM TEST_TABLE T
LEFT JOIN TEST_TABLE T2 ON NOT T.COMMON_SEQ is NULL
AND T.COMMON_SEQ=T2.COMMON_SEQ AND T.ID<>T2.ID
WHERE T.ID=1001
But it doesn't bring back 2 records for ID 1004. This example returns only Richmond record (but I need to return also Marianne record):
SELECT T.ID, T.COMMON_SEQ,T.NAME
FROM TEST_TABLE T
LEFT JOIN TEST_TABLE T2 ON NOT T.COMMON_SEQ is NULL
AND T.COMMON_SEQ=T2.COMMON_SEQ AND T.ID<>T2.ID
WHERE T.ID=1004
How can I improve/rewrite the query to return Richmond and Marianne records when I supply only one ID value (either 1004 or 1005)?
You could use:
SELECT *
FROM TEST_TABLE t
WHERE COMMON_SEQ IN (SELECT COMMON_SEQ
FROM TEST_TABLE t1
WHERE t1.ID = 1004)
OR t.ID = 1004;
DBFiddle Demo
Passing the same parameter twice to handle NULL in COMMON_SEQ.
Try this
SELECT COALESCE (ty.id, tx.id) AS id,
COALESCE (ty.common_seq, tx.common_seq) AS common_seq,
COALESCE (ty.name, tx.name) AS name
FROM test_table tx LEFT OUTER JOIN test_table ty
ON (tx.common_seq = ty.common_seq)
WHERE tx.ID = 1004;
With this you can avoid using IN or EXISTS and this is likely to be more performant.
I have these two tables
CREATE TABLE [dbo].[Things](
[testid] [int] NOT NULL,
[testdesc] [varchar](10) NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[ThingsStaging](
[otherid] [int] NOT NULL,
[testid] [int] NOT NULL
) ON [PRIMARY]
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (1, N'Stuff')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (2, N'Things')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (3, N'Orcs')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (4, N'Grubs')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (5, N'Shrooms')
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 1)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 2)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 3)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (2, 3)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (2, 4)
;with allThings(otherid, descs)
as
(
select ts.otherid ,
stuff ((select ', ' + blah.testdesc as [text()]
from (
select distinct t.testdesc
from Things as t
where t.testid = ts.testid ) as blah
for xml path('')), 1, 1, '') as stuffs
from ThingsStaging as ts
)
select *
from allThings
Now when run this query, I get
otherid stuffs
1 Stuff
1 Things
1 Orcs
2 Orcs
2 Grubs
But I should get:
otherid stuffs
1 Stuff, Things, Orcs
2 Orcs, Grubs
I'm not understanding what I'm doing wrong.
I understand what I did wrong. Code will explain better.
select otherid, stuff((select ', ' + t.testdesc as [text()]
from Things as t
inner join ThingsStaging as its on t.testid = its.testid
where its.otherid = ts.otherid
for xml path('')), 1, 1, '') as descs
from ThingsStaging as ts
group by otherid
I want to insert multiple rows in a single table. How can I do this using single insert statement?
Wrap each row of values to be inserted in brackets/parenthesis (value1, value2, value3) and separate the brackets/parenthesis by comma for as many as you wish to insert into the table.
INSERT INTO example
VALUES
(100, 'Name 1', 'Value 1', 'Other 1'),
(101, 'Name 2', 'Value 2', 'Other 2'),
(102, 'Name 3', 'Value 3', 'Other 3'),
(103, 'Name 4', 'Value 4', 'Other 4');
You can use SQL Bulk Insert Statement
BULK INSERT TableName
FROM 'filePath'
WITH
(
FIELDTERMINATOR = '','',
ROWTERMINATOR = ''\n'',
ROWS_PER_BATCH = 10000,
FIRSTROW = 2,
TABLOCK
)
for more reference check
https://www.google.co.in/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=sql%20bulk%20insert
You Can Also Bulk Insert Your data from Code as well
for that Please check below Link:
http://www.codeproject.com/Articles/439843/Handling-BULK-Data-insert-from-CSV-to-SQL-Server
1--> {Simple Insertion when table column sequence is known}
Insert into Table1
values(1,2,...)
2--> {Simple insertion mention column}
Insert into Table1(col2,col4)
values(1,2)
3--> {bulk insertion when num of selected collumns of a table(#table2) are equal to Insertion table(Table1) }
Insert into Table1 {Column sequence}
Select * -- column sequence should be same.
from #table2
4--> {bulk insertion when you want to insert only into desired column of a table(table1)}
Insert into Table1 (Column1,Column2 ....Desired Column from Table1)
Select Column1,Column2..desired column from #table2
You can use UNION All clause to perform multiple insert in a table.
ex:
INSERT INTO dbo.MyTable (ID, Name)
SELECT 123, 'Timmy'
UNION ALL
SELECT 124, 'Jonny'
UNION ALL
SELECT 125, 'Sally'
Check here
For MSSQL, there are two ways:(Consider you have a 'users' table,below both examples are using this table for example)
1) In case, you need to insert different values in users table. Then you can write statement like:
INSERT INTO USERS VALUES
(2, 'Michael', 'Blythe'),
(3, 'Linda', 'Mitchell'),
(4, 'Jillian', 'Carson'),
(5, 'Garrett', 'Vargas');
2) Another case, if you need to insert same value for all rows(for example, 10 rows you need to insert here). Then you can use below sample statement:
INSERT INTO USERS VALUES
(2, 'Michael', 'Blythe')
GO 10
Hope this helps.
You can use the UNION ALL function
http://blog.sqlauthority.com/2007/06/08/sql-server-insert-multiple-records-using-one-insert-statement-use-of-union-all/
We will import the CSV file into the destination table in the simplest form. I placed my sample CSV file on the C: drive and now we will create a table which we will import data from the CSV file.
DROP TABLE IF EXISTS Sales
CREATE TABLE [dbo].[Sales](
[Region] [varchar](50) ,
[Country] [varchar](50) ,
[ItemType] [varchar](50) NULL,
[SalesChannel] [varchar](50) NULL,
[OrderPriority] [varchar](50) NULL,
[OrderDate] datetime,
[OrderID] bigint NULL,
[ShipDate] datetime,
[UnitsSold] float,
[UnitPrice] float,
[UnitCost] float,
[TotalRevenue] float,
[TotalCost] float,
[TotalProfit] float
)
The following BULK INSERT statement imports the CSV file to the Sales table.
BULK INSERT Sales
FROM 'C:\1500000 Sales Records.csv'
WITH (FIRSTROW = 2,
FIELDTERMINATOR = ',',
ROWTERMINATOR='\n' );
This is my table:
CREATE TABLE [Test].[dbo].[MyTest]
(
[Id] BIGINT NOT NULL,
[FId] BIGINT NOT NULL,
[SId] BIGINT NOT NULL
);
And some data:
INSERT INTO [Test].[dbo].[MyTest] ([Id], [FId], [SId]) VALUES (1, 100, 11);
INSERT INTO [Test].[dbo].[MyTest] ([Id], [FId], [SId]) VALUES (2, 200, 12);
INSERT INTO [Test].[dbo].[MyTest] ([Id], [FId], [SId]) VALUES (3, 100, 21);
INSERT INTO [Test].[dbo].[MyTest] ([Id], [FId], [SId]) VALUES (4, 200, 22);
INSERT INTO [Test].[dbo].[MyTest] ([Id], [FId], [SId]) VALUES (5, 300, 13);
INSERT INTO [Test].[dbo].[MyTest] ([Id], [FId], [SId]) VALUES (6, 200, 12);
So I need 2 select query,
First Select FId, SId that like a distinct in both column so the result is:
100, 11
200, 12
100, 21
200, 22
300, 13
As you see the values of 200, 12 returned once.
Second query is the Id's of that columns whose duplicated in both FId, SId So the result is:
2
6
Does any one have any idea about it?
Standard SQL
SELECT
M.ID
FROM
( -- note all duplicate FID, SID pairs
SELECT FID, SID
FROM MyTable
GROUP BY FID, SID
HAVING COUNT(*) > 1
) T
JOIN -- back onto main table using these duplicate FID, SID pairs
MyTable M ON T.FID = M.FID AND T.SID = M.SID
Using windowing:
SELECT
T.ID
FROM
(
SELECT
ID,
COUNT(*) OVER (PARTITION BY FID, SID) AS CountPerPair
FROM
MyTable
) T
WHERE
T.CountPerPair > 1
First query:
SELECT DISTINCT Fid,SId
FROM MyTest
Second query:
SELECT DISTINCT a1.Id
FROM MyTest a1 INNER JOIN MyTest a2
ON a1.Fid = a2.Fid
AND a1.SId = a2.SId
AND a1.Id <> a2.Id
I cannot test them, but I think they should work...
first:
select distinct FId,SId from [Test].[dbo].[MyTest]
second query
select distinct t.Id
from [Test].[dbo].[MyTest] t
inner join [Test].[dbo].[MyTest] t2
on t.Id<>t2.Id and t.FId=t2.FId and t.SId=t2.SId
Part 1 is as mentioned above distinct.
This will resolve second part.
select id from [Test].[dbo].[MyTest] a
where exists(select 1 from [Test].[dbo].[MyTest] where a.[SId] = [SId] and a.[FId] = [FId] and a.id <> id)