Update multiple rows with different values - sql

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

Related

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%'

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

How to grab data from joined tables in a list of values condition?

I have three tables: Images table, Product table, and ProductGallery table. My Images table have two columns
In this way:
ID Path
1 JeffAtwood.jpg
2 GeoffDalgas.jpg
3 Jarrod Dixon.jpg
4 JoelSpolsky.jpg
My Products table have two columns :
ID Image ID
1 1
2 2
3 3
4 4
My ProductGallery has three columns
ID ImageID ProductID
1 1 1
2 2 1
3 3 1
4 4 1
5 1 2
6 2 2
7 3 2
8 4 2
I need to create a stored procedure that return for me all the paths for list of products
So I have a parameter called #ids NVARCHAR(MAX)
in which all the products ids that i need is there with a comma separating each value.
so I have :
#ids = '1' + ','+ '2'+',' ..... and so on
Any one can help me to write the sql statement does the job for me ?
So far I have this
Declare #Ids VARCHAR(MAX)
select #Ids = '1';
select P.ID ,I.Path from Images I
left outer join Products P on (I.ID IN(select ImageID from Products where ID in (SELECT Items FROM Split(#Ids,','))))
left outer join ProductGallery PG on (PG.ImageID = I.ID)
WHERE PG.ProductID IN(SELECT Items FROM Split(#Ids,',')) AND P.ID IN
(SELECT Items FROM Split(#Ids,','))
GROUP BY P.ID, I.Path
Notice #Ids parameter is already filled with values and I will pass it from my C# code.
Not at a machine to test but you could try
select I.Path from Images I
left outer join Products P on P.ImageID = I.ID
where CHARINDEX(convert(varchar, P.ID), #ids) > 0
By looking at your query, I assume you already have a function to split a delimited string.
Try this (to get images from product table, as per comment):
Select p.Id ProductId, i.Path imagePath
From Products p
Join Images i on p.imageId = i.Id
Where p.Id in (
--your Split() function here
SELECT Items FROM dbo.Split(#Ids,',')
)

Text search of a many-to-many data relation

I know this must have been answered before here, but I simply can't find a matching question.
Using a LIKE '%keyword%', I want to search a many-to-many data relationship in a MSSQL database and reduce it to a one-to-one result set. The two tables are joined through a linking table. Here's a very simplified version of what I'm talking about:
Books:
book_ id title
1 Treasure Island
2 Poe Collected Stories
3 Invest in Treasure Islands
Categories:
category_id name
1 Children
2 Adventure
3 Horror
4 Classic
5 Money
BookCategory:
book_id category_id
1 1
1 2
1 4
2 3
2 4
3 5
What I want to do is search for a phrase in the title (e.g. '%treasure island%') and get matching Books records that contain the search string and the single highest matching Categories record that goes with each book -- I want to discard the lesser category records. In other words, I'm looking for this:
book_id title category_id name
1 Treasure Island 4 Classic
3 Invest in Treasure Islands 5 Money
Any suggestions?
Try this. Filter your lookup table, then join:
With maxCategories AS
(select book_id, max(category_id) as category_id from BookCategory group by book_id)
select Books.book_id, Books.Title, Categories.category_id, Categories.name
from Books
inner join maxCategories on (Books.book_id = maxCategories.book_id)
inner join Categories on (Categories.category_id = maxCategories.category_id)
where Books.title like '%treasure island%'
Try:
select * from
(select b.*,
c.*,
row_number() over (partition by bc.book_id
order by bc.category_id desc) rn
from Books b
join BookCategory bc on b.book_id = bc.book_id
join Categories c on bc.category_id = c.category_id
where b.name like '%treasure island%') sq
where rn=1