Adding column to table and automatically UNION tables afterwards - sql

I have the following problem:
I have a table with distinct pairs of ID and Indicator.
Table A:
ID Indicator
----------------------
1 1
1 2
1 3
2 1
2 2
2 3
----------------------
And a second table with distinct names.
Table B:
Names
-------
John
Lea
Peter
--------
What I want is a column in table A with the names of Table B for every ID-Indicator pair:
Outcome:
ID Indicator Names
----------------------------------
1 1 John
1 2 John
1 3 John
2 1 John
2 2 John
2 3 John
1 1 Lea
1 2 Lea
1 3 Lea
2 1 Lea
2 2 Lea
2 3 Lea
1 1 Peter
1 2 Peter
1 3 Peter
2 1 Peter
2 2 Peter
2 3 Peter
----------------------------------
In reality Table B, with the names, is really long, so a manual solution like:
SELECT ID, Indicator, Names = 'John'
FROM TableA
UNION
SELECT ID, Indicator, Names = 'Lea'
FROM TableA
Is not feasible. Is there a non-manual solution to this problem?
Any help is highly appreciated!

You want to join each row in TableA with each row in TableB, this is known as a cross join, as commented. The number of rows output will be A * B.
If you want all columns from both tables the syntax is simply
select *
from TableA cross join TableB

Related

T-SQL - How to use results of a query to select multiple rows based on a count

Considering the below example Person table, I am looking for a way to return multiple rows based on an X value. So, if the BagsOut count is, say 3, I would want 3 copies of the row returned or if it was 2 then 2 copies should be returned, and so on:
ID Name BagsOut
1 Ken 1
2 Dave 3
3 Ben 2
Desired result:
ID Name BagsOut
1 Ken 1
2 Dave 3
2 Dave 3
2 Dave 3
3 Ben 2
3 Ben 2
Is it possible to write this into a single query? I am using T-SQL.
Many thanks in advance for looking.
you can use recursive CTE to achieve this.
declare #t table(ID int, Name char(5), BagsOut int)
insert into #t values
(1 ,'Ken', 1)
,(2 ,'Dave', 3)
,(3 ,'Ben', 2)
;with cte_bags as
(
select id, name, BagsOut,1 as currentRow from #t
union all
select id, name, BagsOut, currentRow+1
from cte_bags
where currentRow < BagsOut)
select id, name, BagsOut from cte_bags
order by id
id
name
BagsOut
1
Ken
1
2
Dave
3
2
Dave
3
2
Dave
3
3
Ben
2
3
Ben
2

Why does the cte return the error that it does not exist?

Here is my code
WITH CTE AS(
SELECT COUNT(CASE name WHEN 'John' THEN 1 END) OVER (PARTITION BY BlockID ORDER BY Step) AS Johns
FROM dbo.YourTable)
DELETE FROM CTE
WHERE Johns >= 1;
SELECT *
FROM dbo.YourTable;
It returns me the following error when I run the code in the notebook
ERROR: syntax error at or near "DELETE"
But I can't seem to find any mistake in the query
When I try to do it in online compiler it returns the error that relation "cte" does not exist
Maybe this errors can be related?...
Here what I'm trying to do with cte:
My first table:
Block_id step name
1 1 Marie
1 2 Bob
1 3 John
1 4 Lola
2 1 Alex
2 2 John
2 3 Kate
2 4 Herald
3 1 Alec
3 2 Paul
3 3 Rex
As you can see data frame is sorted by block_id and then by step. I want to delete only in one block_id everything after the row where I have name John(the row with John as well). So the desired output would be
Block_id step name
1 1 Marie
1 2 Bob
2 1 Alex
3 1 Alec
3 2 Paul
3 3 Rex
Create a CTE that returns for each Block_id the step of the first John.
Then join the table to the CTE:
WITH cte AS (
SELECT Block_id, MIN(step) step
FROM tablename
WHERE name = 'John'
GROUP BY Block_id
)
DELETE FROM tablename t
USING cte c
WHERE c.Block_id = t.Block_id AND c.step <= t.step
See the demo.

postgresql statement prob

I have two table A and B as following.
A:
key type
0 t
1 f
2 t
3 f
4 t
5 t
.......
B:
key name
0 Mary
0 Tony
0 Krolik
1 Tom
2 Tony
3 Tony
3 Mary
3 Tom
4 Tony
4 Tim
5 Tim
5 Mary
5 Wuli
.....
I hope to find top n occurence name that it's type is 'f'.
For example, in A, the type of key 1 and 3 are 'f', we find key 1 and 3 in table B, there are 2 'Tom' and 1 'Mary' and 1 'Tony'.
1 Tom
3 Tony
3 Mary
3 Tom
if n = 1 and the table is just showed as before, we hope to get 'Tom', because its occurence is top 1.
How can I write sql statement to satisfy these requirement?
I write something like below, but it is wrong. Can anyone help me? I assume n = 20.
SELECT DISTINCT TOP 20 name
FROM B
WHERE key IN (
SELECT key
FROM A
WHERE "type" = 'f'
)
GROUP BY name
ORDER BY DESC;
You don't seem to need aggregation. And the equivalent of top in Postgres is limit or fetch first <row> rows:
SELECT name, key
FROM B
WHERE B.key IN (SELECT A.key
FROM A
WHERE "type" = 'f'
)
ORDER BY key;
This corresponds to the results presented in the question. Your description doesn't quite match those results.

Cross Join for Missing table (Select all and Select or Insert the Missing Row Only)

I have two table and have to fill in a list of missing values in one of the table based on the other one. First table has student's information and the second table has Grade related info, Grade and Grade description.
Table One
ID Name yearWithUs Grade Course Level
1 Jim 2004 4 4
2 Jim 2004 4 1
2 Jim 2003 3 3
4 Jim 2002 2 3
4 Jim 2002 2 1
3 Jim 2001 1 2
3 Jim 2001 1 1
Table two -- logic is.. A Student in a higher Course Level can change to a lower Course Level at anytime during the semester. And It can only go downward 1 level at a time. Example: Jim in his second grade first was assigned to attend course in level 3. He need to attend course in level 2 first before he can attend course in level 1. Means. Row for course level 2 at jim's first grade is missing.
Table Two
ID Grade Grade_Desc Course Level Course Desc
1 1 First Grade 1 Basic
2 1 First Grade 2 Normal
3 1 First Grade 3 Hard
4 1 First Grade 4 Expert
5 2 Second Grade 1
6 2 Second Grade 2
7 2 Second Grade 3
8 2 Second Grade 4
. . .
. . .
. . .
Logic of Table Two
ID Grade Grade_Desc Course Level Possible Move
1 1 First Grade 1 Null
2 1 First Grade 2 1
3 1 First Grade 3 2
4 1 First Grade 4 3
Ouptput one ... how to use select statement to return Jim's Grade?
ID Name Grade_Desc Grade yerWithUs Course Level
1 Jim Fourth Grade 4 2004 4
2 Jim Fourth Grade 4 2004 3
3 Jim Fourth Grade 4 2004 2
4 Jim Fourth Grade 4 2004 1
5 Jim Third Grade 3 2003 3
6 Jim Second Grade 2 2002 3
7 Jim Second Grade 2 2002 2
8 Jim Second Grade 2 2002 1
9 Jim First Grade 2 2001 2
10 Jim First Grade 2 2001 1
Output Two..How to retrieve only the missing row into a new temp table?
ID Name Grade_Desc Grade yearWithUs Course Level
2 Jim Fourth Grade 4 2004 3
3 Jim Fourth Grade 4 2004 2
7 Jim Second Grade 2 2002 2
I am currently is using a messy Cursor Statement to do it. The structure looks really messy and hard to debug return errors. I did a lot of research, and saw people use Cross Join to fill the missing portion which looks really clean (See example below)... I have tried the script it myself in many different way by using the cross join example below...obviously, I failed. I found a similar question in stackoverflow..but I am not able to understand how does it work and why without looking at the data....I need help to understand how to use cross join to rerun missing row? and I am open to any other possible solution.
"SELECT calendar.Date,
Category.Cat,
Score = ISNULL(Scores.Score, 0)
FROM Calendar
CROSS JOIN Catogory
LEFT JOIN Scores
ON Scores.Cat = Category.Cat
AND Scores.Date = Calendar.Date
WHERE Calendar.DayOfMonth = 1;"
Inserting missing rows with a join
Thank You
This will produce that output:
select distinct name, grade, Grade_Desc
from one
cross join two
If select is all you want then:
Select row_number() over(order by (select 1)) as id, * from
(Select distinct name from t1)t1
cross join t2
Here is fiddle http://sqlfiddle.com/#!6/a8a42/3
Try this out:
Create #Temp
DECLARE #Name VARCHAR(100) = 'Jim'
SELECT ROW_NUMBER() OVER (ORDER BY B.Grade DESC,B.CourseLevel DESC) ID,
A.Name,
B.Grade_Desc,
B.Grade,
A.YearWithUs,
B.[Course Level]
INTO #temp
FROM
(
SELECT DISTINCT Name,YearWithUs,Grade
FROM TableOne
WHERE Name = #Name
) A
INNER JOIN TableTwo B
ON A.Grade = B.Grade
Output One
SELECT *
FROM #temp
Output Two into #OutputTwo(temp table)
SELECT A.* INTO #OutputTwo
FROM #temp A
LEFT JOIN TableOne B
ON A.Grade = B.Grade
AND A.[Course Level] = B.[Course Level]
WHERE A.Grade IS NULL AND A.[Course Level] IS NULL

SQL: Select criteria for two tables, compare 1 field, return using condition

These are the tables in the query. Want to compare the ID_Skills in the following 2 tables. And in the returning table from the select query, display ID_Skills with condition saying whether or not TrainingRequired (Yes/No)
tblEmployeeCurrentSkills
ID_EmployeeCurrentSkills ID_Employee ID_Skills
1 1 1
2 1 2
3 2 1
tblSkillsRequired
ID_SkillsRequired ID_Employee ID_Skills ID_Position
1 1 1 1
2 1 2 1
3 1 3 1
4 2 3 2
tblSkills
ID_Skills Skill
1 Reading
2 Wiring
3 Stapling
tblPosition
ID_Position Position
1 Tech1
2 Stapler
tblEmployee
ID_Employee EmployeeName
1 Hannah
2 Bob
SQL for qrySkillsGap table - determines whether training is necessary
SELECT tblEmployee.[Employee Name],
tblSkillsRequired.ID_Skills,
tblSkills.Skill,
IIf([tblEmployeeCurrentSkills].[ID_Skills]
Like [tblSkillsRequired].[ID_Skills],"No","Yes") AS TrainingRequired
FROM (tblSkills
INNER JOIN tblSkillsRequired
ON tblSkills.ID_Skills = tblSkillsRequired.ID_Skills)
INNER JOIN (tblEmployee INNER JOIN tblEmployeeCurrentSkills
ON tblEmployee.ID_Employee = tblEmployeeCurrentSkills.ID_Employee)
ON tblSkills.ID_Skills = tblEmployeeCurrentSkills.ID_Skills;
This is the current output:
EmployeeName ID_Skill TrainingRequired
Hannah 1 No
Hannah 1 No
Hannah 2 No
Bob 1 No
Bob 1 No
I want it to display this:
EmployeeName ID_Skill TrainingRequired
Hannah 1 No
Hannah 2 No
Hannah 3 Yes
Bob 1 No
Bob 3 Yes
Thanks for any help!
I was able to create the tables you provided and used a union to bring together the employee skills and required skills.
SELECT te.EmployeeName
, emp.ID_Skills
, CASE WHEN MIN(emp.TrainingRequired) = 0 THEN 'No'
ELSE 'Yes'
END AS TrainingRequired
FROM dbo.tblEmployee AS te
JOIN (SELECT tecs.ID_Employee
, tecs.ID_Skills
, 0 AS TrainingRequired
FROM dbo.tblEmployeeCurrentSkills AS tecs
UNION
SELECT tsr.ID_Employee
, tsr.ID_Skills
, 1 AS TrainingRequired
FROM dbo.tblSkillsRequired AS tsr
) emp
ON te.ID_Employee = emp.ID_Employee
GROUP BY te.ID_Employee
, te.EmployeeName
, emp.ID_Skills
ORDER BY te.ID_Employee
, emp.ID_Skills