Look up items in same table from relationship table SQL - 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%'

Related

How to fill values by referencing other field values in BigQuery SQL?

I have these 2 tables
parents
name
address
a
one
b
two
c
three
children
name
parents
1
a
2
a
3
b
4
a
5
c
6
b
I'd like to get the result like this,
children_address
name
address
1
one
2
one
3
two
4
one
5
three
6
two
children's address is the same as their parents'.
How can I get this result in BigQuery?
Assuming that all childrens have parents, I'd use INNER JOIN to achieve the desired output:
SELECT
c.name, p.address
FROM
parents_table AS p
INNER JOIN
children_table AS c ON p.name = c.parents
ORDER BY
c.name
OUTPUT:
name address
---- -------
1 one
2 one
3 two
4 one
5 three
6 two
If you use LEFT JOIN, you are probably assuming that not all children have a parent. In case that happens, the result with return null on the address column of the output.
Try this using LEFT JOIN
SELECT children.name, address FROM dataset.children children
LEFT JOIN dataset.parents parents ON parents.name = children.parents

Update multiple row values to same row and different columns

I was trying to update table columns from another table.
In person table, there can be multiple contact persons with same inst_id.
I have a firm table, which will have latest 2 contact details from person table.
I am expecting the firm tables as below:
If there is only one contact person, update person1 and email1. If there are 2, update both. If there is 3, discard the 3rd one.
Can someone help me on this?
This should work:
;with cte (rn, id, inst_id, person_name, email) as (
select row_number() over (partition by inst_id order by id) rn, *
from person
)
update f
set
person1 = cte1.person_name,
email1 = cte1.email,
person2 = cte2.person_name,
email2 = cte2.email
from firm f
left join cte cte1 on f.inst_id = cte1.inst_id and cte1.rn = 1
left join cte cte2 on f.inst_id = cte2.inst_id and cte2.rn = 2
The common table expression (cte) used as a source for the update numbers rows in the person table, partitioned by inst_id, and then the update joins the cte twice (for top 1 and top 2).
Sample SQL Fiddle
I think you don't have to bother yourself with this update, if you rethink your database structure. One great advantage of relational databases is, that you don't need to store the same data several times in several tables, but have one single table for one kind of data (like the person's table in your case) and then reference it (by relationships or foreign keys for example).
So what does this mean for your example? I suggest, to create a institution's table where you insert two attributes like contactperson1 and contactperson2: but dont't insert all the contact details (like email and name), just the primary key of the person and make it a foreign key.
So you got a table 'Person', that should look something like this:
ID INSTITUTION_ID NAME EMAIL
1 100 abc abc#inst.com
2 101 efg efg#xym.com
3 101 ijk ijk#fg.com
4 101 rtw rtw#rtw.com
...
And a table "Institution" like:
ID CONTACTPERSON1 CONTACTPERSON2
100 1 NULL
101 2 3
...
If you now want to change the email adress, just update the person's table. You don't need to update the firm's table.
And how do you get your desired "table" with the two contact persons' details? Just make a query:
SELECT i.id, p1.name, p1.email, p2.name, p2.email
FROM institution i LEFT OUTER JOIN person p1 ON (i.contactperson1 = p1.id)
LEFT OUTER JOIN person p2 ON (i.contactperson2 = p2.id)
If you need this query often and access it like a "table" just store it as a view.

SQL replace values in selection many columns

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

SQL: Combination of one column + count

I have a source table containing userIDs and their actions (entries are distinct)
userID | action
1 A
1 B
2 A
3 B
3 C
and I need to get all combinations of two actions together with the number of users who performed both actions.
action1| action2 | number of users
A A 2
A B 1
(A C 0)
B B 2
B C 1
C C 1
A-C is in parenthesis, because I don't need rows in the output containing 0 users.
a row containing twice the same action (A-A) just stores the number of users who performed that action. (user 1 and user 2 performed action A, that's 2 users)
I tried to join the source table with itself, but as it contains more than an million of rows, I ran out of spool space:
SELECT sT1.action, sT2.action, count(distinct sT1.userID)
FROM sourceTable sT1
JOIN sourceTable sT2 ON (sT1.userID=sT2.userID)
GROUP BY 1,2
HAVING sT1.action <= sT2.action
The output itself shouldn't be too big, as the majority of combinations will not exist (0 users performed both actions).
Is there a more efficient way to query what I need?
Thank you in advance.
SELECT sT1.action, sT2.action, count(*)
FROM sourceTable sT1
LEFT INNER JOIN sourceTable sT2 ON (sT1.userID=sT2.userID)
where (st1.RowID <> st1.RowID)
and sT1.action <= sT2.action
GROUP BY st1.action, st2.action
HAVING count(*) > 0
The only problematic this is that you need to discard the case where st1 and st2 are matching the same row.In the SQL above I have assumed that the sourceTable has a PK I've called RowID and exclude the case where its joining a row to itself.
I've also changed the HAVING line as that didn't seem to be what your description of the problem called for: it sounded like it was better in the WHERE clause. The new HAVING clause is actually redundant: it should never have a count(*) of 0, but it won't hurt.

Update multiple rows with different values

I have these 3 tables
Table books (i want to fill categories column with 1 string of categories delimited with a comma)
id categories
1 null
2 null
3 null
... ...
Table categories
id name
1 adventure
2 horror
... ...
Table BooksCategories (a book can have multiple categories)
bookid categoryid
1 1
1 3
2 2
3 1
3 2
... ...
I have a query that gives me something like this
bookid categories
1 horror, adventure
2 action,...,...
Now, I want to update the column categories of my books table to the corresponding value of my query. Is it possible to do that in an update?
Thanks, I hope it is clear enough
You can JOIN your query with table books so you can update the column,
UPDATE a
SET a.categories = b.categories
FROM books a
INNER JOIN
(
-- paste your query here
-- SELECT bookid, categories,.....
) b ON a.id = b.bookid