SQL replace values in selection many columns - sql

I have two tables:
Table Users
UserId Name
1 John
2 Alice
3 Tom
4 Charles
....
23120 Bob
and
Table Clients
Id Name1 Name2 Name3 .... Name2345
1 1 3 450 4
2 2 17 33 1
...
15302920 44 231 5 7
I would like to make a SQL query where for
Clients.Id = 1
the results are like:
Id Name1 Name2 Name3 ... Name2345
1 John Tom Bill Charles
My clients table has thousands of columns and I try to find a way to replace the values in all columns of the selected results (except the ID column) without thousands of joins.
I know that I can use a query of the following type (but I would like to avoid thousands of joins):
SELECT a.ID,
b.name name1,
c.name name2,
d.name name3
FROM clients a
INNER JOIN users b
ON a.name1 = b.userID
INNER JOIN users c
ON a.name2 = c.userID
INNER JOIN users d
ON a.name3 = d.userID
WHERE a.ID = 1
In addtion:
I can't change the data/structure of the "Clients" table but I can change the "Users" table as necessary.
I can't duplicate the "Clients" table as well since it very large and changes rapidly.
The "Clients" table has thousands of columns and millions of rows, but the selected part is always a small enough subset of the table.
Is it possible?

There is no simple query to achieve this since SQL is fundamentally flexible in rows (vertically) and rigid in columns. This is the closest I came up with:
select c.id,
(select name from dbo.users where UserId = c.name1),
(select name from dbo.users where UserId = c.name2),
(select name from dbo.users where UserId = c.name3),
(select name from dbo.users where UserId = c.name4)
from clients c

Related

SQL: Unable to find a join or union to produce the following table

A Pupil table with { ID, LastName}
a Subject Table with {ID, SubjectName}
and a Report Table with {ID, PupilID, SubjectID, Grade}
There is a one-to-many relationship between Pupil and Report Tables, and Subject and Report Tables.
I want to generate a table like this for say subjectID = 1
Pupil.ID Pupil.LastName SubjectID Grade
1 --------------Smith ---------- 1 ------------B
2 --------------Jones ---------- 1 ------------NULL
3 -------------Weston ----------1 ------------NULL
4 -------------Knightly ---------1 -----------A
The problem is that the Report table would contain just 2 entries for subject 1:
PupilID SubjectID Grade
----1------- 1 ----------- B
----4------- 1 ----------- A
Left joins don't seem to work since there are only 2 entries in the report table for subject 1
SAMPLE DATA
{Pupil Table}
ID LastName
1 ...Smith
2 ...Jones
3 ...Weston
4 ...Knightly
{Subject Table}
ID SubjectName
1 ....Maths
2 ....Physics
3 ....Chemistry
{Report Table}
ID PupilID SubjectID Grade
1 .......1 ..........1 ..........B
2 .......4 ..........1 ..........A
When I do a search on SubjectID = 1 I want the table:
Pupil.ID .......Pupil.LastName ........SubjectID ...........Grade
1 --------------Smith ---------- 1 ------------B
2 --------------Jones ---------- 1 ------------NULL
3 -------------Weston ----------1 ------------NULL
4 -------------Knightly ---------1 -----------A
Access doesn't do subqueries very easily, so everything gets crammed into the FROM clause with a series of wrapped parentheses. Based on your sample data and my fighting Access to stop being unnecessarily difficult, I came up with this:
SELECT ps.Pupil_ID, ps.LastName, ps.Subject_ID, r.Grade
FROM (SELECT * FROM (SELECT ID AS Pupil_ID, LastName FROM Pupil) p,
(SELECT DISTINCT ID AS Subject_ID FROM Subject)) ps
LEFT JOIN REPORT r ON r.PupilID = ps.Pupil_ID AND r.SubjectID = ps.Subject_ID
ORDER BY Pupil_ID, Subject_ID;
The subquery "ps" is a cartesian join of the Pupil and Subject table views that I specified. At this point, your query would look like this:
(LastName column not shown for clarity)
StudentID|SubjectID
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Now, using that Cartesian join subquery (pupilstudent -> ps), I use a LEFT JOIN to assign the Report table to each unique student's ID and subject ID. Therefore, if a student did not take a particular class, there will be a NULL value in the final result.
I tested this in Access using your sample data and it works on my machine.
Also as a note, it is poor practice to have a field called just ID in each table (e.g. in the Pupil table, ID becomes PupilID). This makes it much easier to use, and it self documents.
Cross join pupil and subject tables and left join result to report table
What you need is a cross join:
SELECT Pupil.ID, Pupil.LastName, SubjectID, Grade FROM
Pupil, Subject LEFT JOIN Report ON Subject.ID=Report.SubjectID
WHERE Subject.ID=1
To combine every pupil with every (or with a particular) subject, use cross join; Then use left join to get the corresponding grades:
select *
from pupil p cross join (select * from subject where id = 1) s
left join report on subjectId = s.id and pupilId = p.id

SQL Inner Join Two Foreign Keys

I have two tables (Users and Pairs). The Pairs table contains 3 columns, an ID and then a user1ID and user2ID.
Users
ID firstName surname
------------------------------
1043 john doe
2056 jane doe
Pairs
ID user1ID user2ID
------------------------------
1 1043 2056
I'm then looking at using a select statement to get the user details base on the ID of the Pairs table:
SELECT users1.*, users2.*
FROM Pairs
JOIN Users users1 ON Pairs.user1ID = users1.IDNumber
JOIN Users users2 ON Pairs.user2ID = users2.IDNumber
WHERE Pairs.ID = 1
Which returns the right details for the two users, however they're all on one row, how can I get it to return each user on a separate row as they are in the Users table?
SELECT users1.*, users2.*
FROM Pairs
JOIN Users
ON Pairs.user1ID = users.IDNumber
OR Pairs.user2ID = users.IDNumber
WHERE Pairs.ID = 1
Just use an OR statement in your ON condition instead of 2 joins.
IN will work also.
SELECT *
FROM Pairs p
JOIN Users u ON u.ID IN (p.user1ID, p.User2ID)
WHERE p.ID = 1

Table Join Distinct Field

The problem which I am having is joining two tables. One table contains all the generic data and the second table contains old fields which have been given specific values. The exemplary tables below should help to clarify my setup.
Table 1 (Generic Data)
ParaIndex ParaName ParaDefault
1 Cat 15
2 Fish 8
3 Dog 3
Table 2 (Specific Data)
Project ParaIndex ParaValue
John 1 6
John 2 7
Alan 3 9
The goal then is to join these tables to get a single table:
Table 3 (Table Join on ParaIndex for 'John')
ParaName ParaIndex ParaValue ParaDefault
Cat 1 6 15
Fish 2 7 8
Dog 3 3
So Table 3 would return all rows from Table 1 but would only show values for ParaValue where they are not empty. E What I have tried so far is a combination of changing the join type, distinct select, group by, select subqueries, and suggestions mentioned in other posts.
The end goal is then to use this query in vb.net as par of a form.
The closest which I have gotten is to return the requested data in table 3, but it would exclude rows which are not requested (e.g. if the query is for 'John' it would then exclude the parameters marked by 'Alan' which is 3-Dog in this case).
SELECT t1.ParaName, t1.ParaIndex, t2.ParaValue, t1.ParaDefault
FROM Table1 AS t1LEFT OUTER JOIN Table2 AS t2
ON t1.ParaIndex = t2.ParaIndex
WHERE (((t2.ParaIndex) is null) OR t2.Project = 'John')
You have to use a LEFT OUTER JOIN:
SELECT t1.ParaName,
t1.ParaIndex,
COALESCE(CAST(t2.ParaValue AS VARCHAR(10), '') AS ParaValue,
t1.ParaDefaule,
FROM dbo.Table1 t1
LEFT OUTER JOIN dbo.Table2 t2
ON t1.ParaIndex = t2.ParaIndex
WHERE t2.Project = 'John'
ORDER BY t1.ParaIndex

Look up items in same table from relationship table SQL

I'm trying to create a query where I search for a value contained in a table (called objects), look up it's id in a table called relationships and find the id's of related objects and look them up in the original table.
Objects Relationships
ID Value ID RelatedToID RelatedFromID
1 Name A 2 1
2 Name1 B 3 1
3 Name2 C 4 1
4 Name3 D 2 3
Query Name > return Name1, Name2, Name3
To add some background SCCM stores windows updates and update groups within the same table and creates relationships between objects in the same table and stores them in a separate table.
Try something like:
SELECT *
FROM Objects o1
INNER JOIN RelationShips r ON
o1.ID = r.RelatedFromID
INNER JOIN Objects o2 ON
r.RelatedToId = o2.ID
WHERE o1.Value LIKE '%The value you are searching for%'

multiple conditions in same column with relation

Here is the case:
There is a user table
id email orders_counter
=================================
1 a#a.com 5
2 b#b.com 3
3 c#c.com 0
And a user data table for user's other data
id user_id title value
=======================================
1 1 Name Peter Johnson
2 1 Tel 31546988
3 2 Name Alan Johnson
4 2 Tel 56984887
If I want to fetch all user that
1, orders_counter greater then 3
2, Name contain 'Johnson'
3, Tel contain '88'
AT THE SAME TIME
What is my sql, and if I want to do it rubyonrails way
what is the ActiveRecord code
I know I can it one by one and then join all of them together, but it waste too much resource while conditions build up
Select * From `user` u
inner join `userdata` d on d.user_id=u.id and d.title='Name' and d.value like '%Johnson%'
inner join `userdata` c on c.user_id=u.id and c.title='Tel' and c.value like '%88%'
where orders_counter > 3
the way that you've got your user data table structured, you'll almost always have to join on that table several times in order to "pivot" those values into columns. I'd recommend just creating a table that has name and tel as columns. then the query becomes a lot more simple
select * from `user` u
inner join `user_data` d on d.Tel like '%88%' and d.Name like '%johnson%'
where u.orders_counter > 3
try this one up,
SELECT a.*, b.*
FROM user a
INNER JOIN data b
ON a.id = b.user_ID
WHERE a.orders_counter > 3 AND
(b.title = 'NAME' AND b.value like '%johnson%') AND
(b.title = 'TEL' AND b.tel like '%88%')
try this:
select *
from user U join user_data D
on U.id=D.user_id
where U.orders_counter>3
and D.title='Name' and value like '%Johnson%'
and D.title='Tel' and value like '%88%'