SQL Query second relation - sql

i have a problem i want to take SQL query language that returns the employee's (id) supervisor to his supervisor.
I have a tab employee
create table employee (
id int not null,
surname varchar(50),
name varchar(30),
boss_id int)

You may try this...
select a.id, b.boss_id
from employee as a
inner join employee as b on a.boss_id=b.id
For test case
create table DemoTable
(
accountid bigint
,parentid bigint
,accountname nvarchar(128)
)
insert DemoTable(accountid,parentid,accountname)
select 1, null, 'Root'
union select 2, 3, 'Child1'
union select 3, 1, 'Child2'
Query:
select a.accountid, b.parentid from DemoTable as a
inner join DemoTable as b on a.parentid=b.accountid
output is as : pass accountid as 2
accountid parentid
2 1
Here 2 >> 3 >> 1

Related

Join two tables multiple times on same column with a lookup table in between

This has probably been answered but, its hard to search for this question, as you can see in my confusing title.
Anyhow, I hope this example will help:
The tricky part is the one to many relationship in the parameter lookup table.
Ive tried using multiple joins and aliases resulting in a hugh number of rows since Im getting every 'amount' for every 'price'.
SELECT paraval.month, paraval.value as amount, paraval2.value as price, trade.position
FROM trade
INNER JOIN parameter para on trade.tID=para.tID and para.name = 'amount'
INNER JOIN parametervalues paraval on para.pID=paraval.pID
INNER JOIN parameter para2 on trade.tID=para2.tID and para2.name = 'price'
INNER JOIN parametervalues paraval2 on para2.pID=paraval2.pID
WHERE trade.type = 'cert'
Guessing I need sub-queries, but not sure where to place them.
EDIT add some SQL code structure :
CREATE TABLE #Trade
(
tID int PRIMARY KEY,
type varchar(50),
position int
);
CREATE TABLE #Parameter
(
pID int PRIMARY KEY,
tID int,
name varchar(50)
);
CREATE TABLE #ParameterValue
(
pID int,
smonth varchar(50),
value varchar(50));
INSERT INTO #Trade
SELECT 1, 'stock', 1
UNION
SELECT 2, 'stock', 2
UNION
SELECT 3, 'cert', 3
INSERT INTO #Parameter
SELECT 1,1,'amount'
UNION
SELECT 2,1,'price'
UNION
SELECT 3,2,'amount'
UNION
SELECT 4,2,'price'
UNION
SELECT 5,3,'amount'
UNION
SELECT 6,3,'price'
INSERT INTO #ParameterValue
SELECT 1,1,'5'
UNION
SELECT 2,1,'500'
UNION
SELECT 3,1,'15'
UNION
SELECT 4,1,'300'
UNION
SELECT 5,1,'5'
UNION
SELECT 5,2,'10'
UNION
SELECT 5,3,'5'
UNION
SELECT 6,1,'100'
UNION
SELECT 6,2,'200'
UNION
SELECT 6,3,'300'
-- SELECT * FROM #Trade
-- SELECT * FROM #Parameter
-- SELECT * FROM #ParameterValue
DROP TABLE #Trade
DROP TABLE #Parameter
DROP TABLE #ParameterValue
I think the best way for build your excepted output and relevant schema you have to use pivot with dynamic sql because in next day it possible to have some new values it’s the principal of your structure.
But i think this query can be respond :
SELECT paraval.month, (case when para. name = 'amount' then max(paraval.value) else null end)as amount, (case when para. name = 'price' then max(paraval.value) else null end) as price, max(trade.position) as position
FROM trade
INNER JOIN parameter para on trade.tID=para.tID
INNER JOIN parametervalues paraval on para.pID=paraval.pID
WHERE trade.type = 'cert'
Group by paraval.month
EDIT correction off previous query :
CREATE TABLE #Trade
(
tID int PRIMARY KEY,
type varchar(50),
position int
);
CREATE TABLE #Parameter
(
pID int PRIMARY KEY,
tID int,
name varchar(50)
);
CREATE TABLE #ParameterValue
(
pID int,
smonth varchar(50),
value varchar(50));
INSERT INTO #Trade
SELECT 1, 'stock', 1
UNION
SELECT 2, 'stock', 2
UNION
SELECT 3, 'cert', 3
INSERT INTO #Parameter
SELECT 1,1,'amount'
UNION
SELECT 2,1,'price'
UNION
SELECT 3,2,'amount'
UNION
SELECT 4,2,'price'
UNION
SELECT 5,3,'amount'
UNION
SELECT 6,3,'price'
INSERT INTO #ParameterValue
SELECT 1,1,'5'
UNION
SELECT 2,1,'500'
UNION
SELECT 3,1,'15'
UNION
SELECT 4,1,'300'
UNION
SELECT 5,1,'5'
UNION
SELECT 5,2,'10'
UNION
SELECT 5,3,'5'
UNION
SELECT 6,1,'100'
UNION
SELECT 6,2,'200'
UNION
SELECT 6,3,'300'
/***/
-- Perform select
/***/
SELECT t.tID, paraval.smonth, MAX(case when para.name = 'amount' then paraval.value else null end)as amount, MAX(case when para.name = 'price' then paraval.value else null end) as price, max(T.position) as position
FROM #Trade T
INNER JOIN #Parameter para on T.tID=para.tID
INNER JOIN #ParameterValue paraval on para.pID=paraval.pID
Group by T.tId, paraval.smonth
/***/
DROP TABLE #Trade
DROP TABLE #Parameter
DROP TABLE #ParameterValue
RESULT :
tID smonth amount price position
1 1 5 500 1
2 1 15 300 2
3 1 5 100 3
3 2 10 200 3
3 3 5 300 3

SQL Get values from other tables before Insert Into query command

I am wanting to create a query that allows me to look up a number that's presented in another table before I add that ID's name to the needed table being called by the query.
An example:
Table1
ID |name |nameID |network |...
----------------------------------
5 |Bob |4 |NPOW |...
6 |Billy |8 |BGER |...
Table2
ID |name |nameID |network |...
----------------------------------
3 |Stan |2 |ERFDT |...
Table3
ID |name |nameID |network |...
----------------------------------
3 |Steve |3 |FRVS |...
Table4 (The table I am inserting the new rows below into)
ID |name |nameID |network |...
----------------------------------
On my page these are the new values I need to add to the table4 above:
Name |ID |network |...
------------------------
Nick |4 |RFGH |...
Tony |3 |ESLO |...
James |2 |HUII |...
Rusty |3 |ERNM |...
Now what I am wanting to do is see what column ID equals X and place that name into Table4.
So doing that the outcome for table4 should look like this after the insert:
ID |name |nameFromID |network |...
--------------------------------------
1 |Nick |Bob |RFGH |...
2 |Tony |Steve |ESLO |...
3 |James |Stan |HUII |...
4 |Rusty |Steve |ERNM |...
So what would the INSERT INTO Table4 query look like for doing this?
You can do this with a view, some joins, and a temp table or some other staging table with session scoping. Here's a temp table approach.
The view to bring all the different tables into a single queryable form:
CREATE VIEW vAllNames
AS
SELECT [Name], NameID FROM Table1 UNION
SELECT [Name], NameID FROM Table2 UNION
SELECT [Name], NameID FROM Table3
The above assumes that NameId cannot be duplicated across these tables, so I've used UNION instead of UNION ALL. Otherwise you'll need to tell us how you want the name to resolve when the id matches successfully to multiple tables. Would you want multiple records inserted into table 4, only the first match, some kind of concatenation, etc.
The temp table so we have something to select from for the insertion unless you want to insert one at a time (you could also do this with a session scoped persistent table or something along those lines):
CREATE TABLE #TempDataToInsert
(
[Name] NVARCHAR(256),
ID INT,
network CHAR(4)
)
Once you've created those you can insert the data from your page directly into TempDataToInsert. Once your data is staged there you can run the final insert into:
INSERT INTO Table4
([Name], nameFromID, network) -- Assumes ID is an identity column
SELECT
tempData.[Name], allNames.[Name], tempData.network
FROM
#TempDataToInsert tempData
LEFT OUTER JOIN vAllNames allNames ON tempData.ID = allNames.NameID -- assumes no match is still valid for insertions
You'll need to clean up the temp table afterwards and I've made some assumptions about your schema but this should point you in the right direction.
CREATE TABLE #Temp0
(
ID INT,
[Name] VARCHAR(100),
NameId INT,
Network VARCHAR(100)
);
INSERT INTO #Temp0
(
ID,
Name,
NameId,
Network
)
VALUES
(5, 'Bob', 4, 'NPOW'),
(6, 'Billy', 8, 'BGER');
CREATE TABLE #Temp1
(
ID INT,
[Name] VARCHAR(100),
NameId INT,
Network VARCHAR(100)
);
INSERT INTO #Temp1
(
ID,
Name,
NameId,
Network
)
VALUES
(3, 'Stan', 2, 'ERFDT');
CREATE TABLE #Temp2
(
ID INT,
[Name] VARCHAR(100),
NameId INT,
Network VARCHAR(100)
);
INSERT INTO #Temp2
(
ID,
Name,
NameId,
Network
)
VALUES
(3, 'Steve', 3, 'FRVS');
SELECT *
INTO #Temp
FROM
(
SELECT [Name],
NameId
FROM #Temp0
UNION
SELECT [Name],
NameId
FROM #Temp1
UNION
SELECT [Name],
NameId
FROM #Temp2
) AS Temp;
CREATE TABLE #Temp3
(
[Name] VARCHAR(100),
Id INT,
Network VARCHAR(100)
);
INSERT INTO #Temp3
(
Name,
Id,
Network
)
VALUES
('Nick', 4, 'RFGH'),
('Tony', 3, 'ESLO'),
('James', 2, 'HUII'),
('RUSTY', 3, 'ERNM');
CREATE TABLE #Table4
(
ID INT IDENTITY(1, 1),
[Name] VARCHAR(100),
NameFormId VARCHAR(100),
Network VARCHAR(100)
);
INSERT INTO #Table4
SELECT T2.Name,
T1.Name,
T2.Network
FROM #Temp T1
JOIN #Temp3 T2
ON T1.NameId = T2.Id;
SELECT *
FROM #Table4;
The following code demonstrates how to match data on NameId between tables. It assumes that the Names being added are unique. If there are multiple NameId matches between input tables then the earliest match is given preference. Multiple NameId matches within a single input table give preference to the lowest Id.
-- Sample data.
declare #Table1 as Table ( Id Int, Name VarChar(10), NameId Int, Network VarChar(10) );
insert into #Table1 ( Id, Name, NameId, Network ) values
( 5, 'Bob', 4, 'NPOW' ), ( 6, 'Billy', 8, 'BGER' );
select * from #Table1;
declare #Table2 as Table ( Id Int, Name VarChar(10), NameId Int, Network VarChar(10) );
insert into #Table2( Id, Name, NameId, Network ) values
( 3, 'Stan', 2, 'ERFDT' );
select * from #Table2;
declare #Table3 as Table ( Id Int, Name VarChar(10), NameId Int, Network VarChar(10) );
insert into #Table3 ( Id, Name, NameId, Network ) values
( 3, 'Steve', 3, 'FRVS' ),
( 4, 'Steven', 3, 'FRVS' ), -- Note duplicate NameId value.
( 9, 'Stanley', 2, 'VOOT' ); -- Note duplicate NameId value.
select * from #Table3;
declare #ValuesToAdd as Table ( Name VarChar(10), NameId Int, Network VarChar(10) );
insert into #ValuesToAdd ( Name, NameId, Network ) values
( 'Nick', 4, 'RFGH' ), ( 'Tony', 3, 'ESLO' ),
( 'James', 2, 'HUII' ), ( 'Rusty', 3, 'ERNM' );
select * from #ValuesToAdd;
-- Process the data.
declare #Table4 as Table ( Id Int Identity, Name VarChar(10), NameId Int,
NameFromId VarChar(10), Network VarChar(10) );
-- Demonstrate the matching.
select Name, NameId, NameFromId, Network
from (
select VTA.Name, VTA.NameId, N.Name as NameFromId, VTA.Network,
Row_Number() over ( partition by VTA.Name order by NameRank, Id ) as RN
from #ValuesToAdd as VTA inner join ( -- Use left outer join if there might not be a match on NameId .
select Id, Name, NameId, 1 as NameRank from #Table1 union all
select Id, Name, NameId, 2 from #Table2 union all
select Id, Name, NameId, 3 from #Table3 ) as N on N.NameId = VTA.NameId ) as PH
--where RN = 1; -- Pick the match from the earliest table.
-- Insert the results.
insert into #Table4
select Name, NameId, NameFromId, Network
from (
select VTA.Name, VTA.NameId, N.Name as NameFromId, VTA.Network,
Row_Number() over ( partition by VTA.Name order by NameRank, Id ) as RN
from #ValuesToAdd as VTA inner join ( -- Use left outer join if there might not be a match on NameId .
select Id, Name, NameId, 1 as NameRank from #Table1 union all
select Id, Name, NameId, 2 from #Table2 union all
select Id, Name, NameId, 3 from #Table3 ) as N on N.NameId = VTA.NameId ) as PH
where RN = 1; -- Pick the match from the earliest table.
select * from #Table4;

Displaying multiple select in a single cell

Please help me to solve the following issue .
consider i have two tables in a Database
1.employee 2.Details
In employee table data will be
eid ename level
1 x 9th
2 y 10th
In Address Table data will be
AId eid location Adreess_type
1 1 india permananet
2 1 US Temporary
3 2 Japan permananet
4 2 China Temporary
I need output in the below format
eid ename fulllocation
1 X INDIA -US
2 y Japan-CHINA
Try this:
SELECT
e.eid,
e.name,
GROUP_CONCAT(a.location SEPARATOR '-') AS fulllocation
FROM
employee as e
INNER JOIN address as a
ON e.eid = a.eid
GROUP BY
e.eid
select employee.eid, employee.ename, t.fulllocation
from employee
inner join (select eid, group_concat(location SEPARATOR '-') as fulllocation from Address group by eid) t
on employee.eid = t.eid
Consider that GROUP_CONCAT have some limitations, what is this and how can change (if needed) it? please check documentation for this.
DECLARE #t1 TABLE
(
eid int NOT NULL,
ename varchar(50),
level varchar(50)
)
DECLARE #t2 TABLE
(
aid int NOT NULL,
eid int,
location varchar(50),
address_type varchar(50)
)
INSERT INTO #t1 SELECT 1, 'x', '9th'
INSERT INTO #t1 SELECT 2, 'y', '10th'
INSERT INTO #t2 SELECT 1, 1, 'india', 'permanent'
INSERT INTO #t2 SELECT 2, 1, 'US', 'temporary'
INSERT INTO #t2 SELECT 3, 2, 'Japan', 'permanent'
INSERT INTO #t2 SELECT 4, 2, 'China', 'temporary'
SELECT * FROM #t1
SELECT * FROM #t2
SELECT t1.eid, t1.ename, t2.fullLocation
FROM #t1 AS t1
INNER JOIN (
SELECT eid, COUNT(*) AS noofrecs
, fullLocation = LTRIM(RTRIM(ISNULL(STUFF(
(
SELECT DISTINCT '-' + CAST(t2.location as nvarchar(max))
FROM #t2 t2
WHERE t1.eid = t2.eid
FOR XML PATH (''), TYPE).value('.', 'nvarchar(max)'
), 1, 1, ''), '')))
FROM #t2 as t1
GROUP BY eid
) AS t2
ON t1.eid = t2.eid
DECLARE #t1 TABLE
(
eid int NOT NULL,
ename varchar(50),
level varchar(50)
)
DECLARE #t2 TABLE
(
aid int NOT NULL,
eid int,
location varchar(50),
address_type varchar(50)
)
INSERT INTO #t1 SELECT 1, 'x', '9th'
INSERT INTO #t1 SELECT 2, 'y', '10th'
INSERT INTO #t2 SELECT 1, 1, 'india', 'permanent'
INSERT INTO #t2 SELECT 2, 1, 'US', 'temporary'
INSERT INTO #t2 SELECT 3, 2, 'Japan', 'permanent'
INSERT INTO #t2 SELECT 4, 2, 'China', 'temporary'
SELECT * FROM #t1
SELECT * FROM #t2
SELECT b.eid,b.ename
, STUFF((SELECT '_ ' + a.location FROM #t2 A
Where A.eid=B.eid FOR XML PATH('')),1,1,'') As fulllocation
From #t1 B
Group By b.eid,b.ename
In order to preserve the order of the locations, you could work along
SELECT
e.eid
, e.ename
, CONCAT_WS('-', p.location, t.location) AS fulllocation
FROM Employee e
JOIN Address p
ON e.eid = p.eid
AND p.address_type = 'permananet'
JOIN Address t
ON e.eid = t.eid
AND t.address_type = 'Temporary'
;
See it in action: SQL Fiddle.
Please comment if and as this requrires adjustment / further detail.

Inserting values into a table based on column values of another table

I would like to insert data into a table based on all the values of a secondary table's column. For example
I have two tables
CREATE TABLE Table1 (
id int identity(1, 1) not null,
FullName varchar(100),
Age int,
CourseID int
)
CREATE TABLE Table2 (
id int identity(1, 1) not null,
Courses int
)
I would like to perform something like this ..
insert into Table1 ('Auser',20,'And the list of Courses that I get from Table2')
Is there a way I can do this in sql server ?
So for one new user you want to insert all available courses?
INSERT INTO Table1
SELECT 'Ausser', 20, t2.Courses
FROM Table2 t2;
Edit: Here's the fiddle: http://sqlfiddle.com/#!3/89470/1/0
Since, you are using SQL Server 2008, you can use the MERGE STATEMENT . Here is a program for your example
CREATE TABLE Table1
(
Id int identity(1, 1) not null,
FullName varchar(100),
Age int,
CourseID int
)
CREATE TABLE Table2
(
ID int identity(1, 1) not null,
Courses int
);
INSERT INTO Table2
SELECT 10 UNION ALL SELECT 20 UNION ALL
SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50;
--The Merge Query
MERGE Table1 AS t1
USING (SELECT * FROM Table2) AS t2
ON t1.CourseID= t2.Courses
WHEN NOT MATCHED THEN
INSERT(FullName,Age,CourseID)
VALUES('Ausser',20,t2.Courses);
SELECT *
FROM Table1
DROP TABLE Table1
DROP TABLE Table2
//Result
Id FullName Age CourseID
1 Ausser 20 10
2 Ausser 20 20
3 Ausser 20 30
4 Ausser 20 40
5 Ausser 20 50

Struggling to count and order by a column by reference in T-SQL database

I'm not sure if I'm writing the following SQL statement correctly? (Using T-SQL)
I have two tables:
Table 1: [dbo].[t_Orgnzs]
[id] = INT
[nm] = NVARCHAR(256)
Table 2: [dbo].[t_Usrs]
[id] = INT
[ds] = NVARCHAR(256)
[oid] = INT (referenced [dbo].[t_Orgnzs].[id])
I need to select elements from Table 2, ordered by the [oid] column ascending from 1 to 16, but the catch is that the [oid] references a string in the Table 1, that I actually need to return as a result.
So for say, if tables were laid out like so:
Table 1:
id nm
1 Name 1
2 Name 2
3 Name 3
4 Name 4
And Table 2:
id ds oid
1 A 2
2 B 4
3 C 1
The resulting query must return:
3 C Name 1
1 A Name 2
2 B Name 4
So here's the SQL I'm using:
WITH ctx AS (
SELECT [id],
[ds],
(SELECT [nm] FROM [dbo].[t_Orgnzs] WHERE [id]=[dbo].[t_Usrs].[oid]) AS organizName,
ROW_NUMBER() OVER (ORDER BY organizName ASC) AS rowNum
FROM [dbo].[t_Usrs]
)
SELECT [id], [ds], organizName
FROM ctx
WHERE rowNum>=1 AND rowNum<=16;
And I'm getting an error: "Invalid column name 'organizName'."
I do not understand the meaning of use ROW_NUMBER() in your case. Why?
CREATE TABLE [t_Orgnzs] ([id] int PRIMARY KEY, [nm] NVARCHAR(256))
GO
CREATE TABLE [t_Usrs] ([id] int, [ds] NVARCHAR(256), [oid] int FOREIGN KEY REFERENCES [t_Orgnzs]([id]))
GO
INSERT [t_Orgnzs] VALUES (1,'Name_1')
INSERT [t_Orgnzs] VALUES (2,'Name_2')
INSERT [t_Orgnzs] VALUES (3,'Name_3')
INSERT [t_Orgnzs] VALUES (4,'Name_4')
GO
INSERT [t_Usrs] VALUES (1,'A',2)
INSERT [t_Usrs] VALUES (2,'B',4)
INSERT [t_Usrs] VALUES (3,'C',1)
GO
SELECT *
FROM [t_Orgnzs]
INNER JOIN [t_Usrs] ON [t_Orgnzs].[id]=[t_Usrs].[oid]
ORDER BY [oid]
How about this one
select id, ds, nm
from
(
select ROW_NUMBER() OVER (ORDER BY o.nm ASC) AS rowNum, u.id, u.ds, o.nm
from t_Usrs u inner join t_Orgnzs o on (u.oid = o.id)
) t
WHERE rowNum>=1 AND rowNum<=16;
SELECT TOP 16 * FROM [t_Orgnzs]
INNER JOIN [t_Usrs]
ON [t_Orgnzs].[id] = [t_Usrs].[oid]
ORDER BY [oid]