how to concatenate multiple rows into one - sql-server-2008

Using SQL 2008 R2
I have two tables and want to create a table like:
output
Input tables
input table 1
inout table 2
I have tried using stuff function as
SELECT o.DEPT_ID,o.CLIENT_ID,
code,
(STUFF((SELECT CAST(', ' + CODE AS VARCHAR(MAX))
FROM ORDERS
WHERE (o.FUNDER_ID = f.FUNDER_ID)
FOR XML PATH ('')), 1, 2, '')) AS funder_code
FROM FUNDERS f
join ORDERS o on o.FUNDER_ID=f.FUNDER_ID
where o.DEPT_ID=111 and CLIENT_ID='B001'
and I'm not getting the output.

First of all, your desired output appears to have the 'name' column from your second input table as a comma-separated list, but your code implies that you want the 'code' column concatenated instead. This solution concatenates the 'name' column.
Second, looking at your input tables, you can't directly use join ORDERS o on o.FUNDER_ID=f.FUNDER_ID because 'B0000000019' does not equal 'F19'. However, once you manipulate those columns so they could be joined, try this:
SELECT DISTINCT o.dept_id, o.client_id
,(STUFF((SELECT distinct CAST(', ' + name AS VARCHAR(MAX))
FROM FUNDERS f
JOIN ORDERS o2 ON o2.funder_id = f.funder_id
FOR XML PATH ('')), 1, 2, '')) AS funder_code
FROM ORDERS o

Related

Mysql Rewrite Column with JSON Array

I want to write an MySQL Query where I replace a JSON Array with Data from another Table.
I have got two Tables, "Reserved" and "Seats". Reserved contains one column "Seats", an JSON Array referring to the ID of the Table "Seats". Table Seats also contains a column "Name". I now want to basically replace the IDs in the JSON Data of the Seats column of the Reserved Table, with the name of the corresponding IDs stored in the Seats Table.
Is there a way to do this in an Mysql Query. I do not know how to pack a query result in a JSON Format and return it as a column
I already tried to utilize JSON_EXTRACT somehow : see test below.
SELECT * FROM `seats` WHERE ID = JSON_EXTRACT('["276", "277", "278"]','$.*')
Basically I want a Query like this:
SELECT *,
JSONCreate(SELECT name from `seats` WHERE seats.id IN JSON_EXTRACT(reserved.seats)) as name
FROM `reserved`
WHERE 1
You can use one of the following solutions.
solution using JSON_SEARCH and JSON_ARRAYAGG
SELECT r.seats, JSON_ARRAYAGG(s.name)
FROM reserved r JOIN seats s ON JSON_SEARCH(r.seats, 'one', CONVERT(s.id, CHAR(10))) IS NOT NULL
GROUP BY r.seats
solution using ... MEMBER OF () and JSON_ARRAYAGG
SELECT r.seats, JSON_ARRAYAGG(s.name)
FROM reserved r INNER JOIN seats s ON CONVERT(s.id, CHAR) MEMBER OF(r.seats)
GROUP BY r.seats
solution using JSON_CONTAINS and JSON_ARRAYAGG
SELECT r.seats, JSON_ARRAYAGG(s.name)
FROM reserved r INNER JOIN seats s ON JSON_CONTAINS(r.seats, JSON_QUOTE(CONVERT(s.id, CHAR))) = 1
GROUP BY r.seats
You can also use JSON_TABLE to solve this:
SELECT JSON_ARRAYAGG(IFNULL(s.name, ''))
FROM reserved r, JSON_TABLE(
r.seats,
"$[*]" COLUMNS (
id CHAR(50) PATH "$"
)
) AS rr LEFT JOIN seats s ON rr.id = s.id
GROUP BY r.seats
Note: You can use INNER JOIN to remove the empty values. Instead of GROUP BY r.seats you should use a id column.
demo on dbfiddle.uk

SQL Server: How to get the extra records comparing 2 tables along with another column which should not be compared

Here is the Sample Data I Have
INSERT INTO MA_NewRevised VALUES
('Vishal','SD','Col',2),
('Shivu','SD','Col',3),
('Pavithra','SD','Col',4),
('Keerthi','SD','Col',5),
('Bharath','SD','Col',6),
('Radhu','SD','Col',2),
('Vanitha','SD','Col',3),
('Anirudh','SD','Col',4),
('Amit','SD','Col',5)
INSERT INTO MA_OldValues VALUES
('Vishal','SD','Col',2),
('Shivu','SD','Col',3),
('Pavithra','SD','Col',2),
('Keerthi','SD','Col',3),
('Bharath','SD','Col',6),
('Radhu','SD','Col',2),
('Vanitha','SD','Col',3),
('Raju','SD','Col',1)
First Code:
SELECT * FROM MA_NewRevised n
EXCEPT
SELECT * FROM MA_OldValues o
The above code will give me.
Second Code
SELECT Name,Groups,CommonColumn FROM MA_NewRevised
EXCEPT
SELECT Name,Groups,CommonColumn FROM MA_OldValues
The Above Code will give me:
But the required Output is
That is, Distinct values with respect to Name, Groups, CommonColumn should be Selected along with the quantity of the new Revised table(First Table)
To your query, which does not return the extra column, but return correct rows, join the original table and retrieve the value of the extra column. Since there is no unique field in your data, you may have to join on all fields.
;with cte as (
SELECT Name,Groups,CommonColumn FROM MA_NewRevised
EXCEPT
SELECT Name,Groups,CommonColumn FROM MA_OldValues
)
select cte.*, n.Quatity -- or n.Quantity, not sure which is the correct name of your column
from cte
inner join MA_NewRevised n on cte.Name = n.Name and cte.Groups = n.Groups and cte.CommonColumn = n.CommonColumn

Combining Data in Two Tables SQL

I'm sure a very basic question, but I'm continue to be stuck:
Table A - image_number, camera_type, total_sales
Table B - image_number, keyword
Table A has one ROW for each image_number - example:
image_number="AXJ789, camera_type="Nikon", total_sales=678
image_number="JIJ123", camera_type="Canon", total_sales=999
image_number="KNI908", camera_type="Sony", total_sales=565
Table B has many ROWs for each image_number - example:
image_number="AXJ789", keyword = "rain"
image_number="AXJ789", keyword = "mountain"
image_number="AXJ789", keyword = "grass"
image_number="AXJ789", keyword = "cloud"
What I'm trying to do is JOIN the two tables so that I can generate the following output:
image_number="AXJ789", camera_type=678, camera_type="Nikon", keyword(1) = "rain", keyword(2) = "mountain", keyword(3) = "grass", keyword(4) = "cloud"
In other words, I want to have all items in each ROW in table A + all the items from table B. For each image_number in Table A, there could be no "keywords" in Table B or 50 keywords - depends on the image.
When I do an INNER JOIN, of course I can get one "keyword" from table B, but I can't figure out how to get all of them.
You can concatenate the keywords together:
select a.*,
(select group_concat(b.keyword)
from b
where b.image_number = a. image_number
) as keywords
from a;
This creates a comma-delimited list of the keywords. This is much simpler (in MySQL) than trying to put them in separate columns. In fact, if you wanted separate columns, I might suggest parsing this result:
select a.*, -- or whatever columns you want
substring_index(keywords, ',' 1) as keyword1,
substring_index(substring_index(keywords, ',' 2), ',', -1) as keyword2,
substring_index(substring_index(keywords, ',' 3), ',', -1) as keyword3,
substring_index(substring_index(keywords, ',' 4), ',', -1) as keyword4
from a left join
(select b.image_number, group_concat(b.keyword) as keywords
from b
group by b.image_number
) b
on b.image_number = a. image_number;
You can generate a comma-separated list of keywords for each image using GROUP_CONCAT and JOIN (but use a LEFT JOIN if an image may have no keywords).
SELECT a.*, GROUP_CONCAT(b.keyword) AS keyword_list
FROM a
JOIN b on b.image_number = a.image_number
GROUP BY a.image_number
Output for your sample data:
image_number camera_type total_sales keyword_list
AXJ789 Nikon 678 rain,mountain,grass,cloud
Demo on dbfiddle
You can then parse this into an array in your application, for example in PHP (if you have read the row into $row):
$keywords = explode(',', $row['keyword_list']);
print_r($keywords);
Output:
Array
(
[0] => rain
[1] => mountain
[2] => grass
[3] => cloud
)

Using column value as clause for IN MySql

I don't understand why this doesn't work, I have a column where I store values comma separated in my "Mysql" database then I want to join two tables to give me results. eg:
SELECT *
FROM users u INNER JOIN
groups g
ON u.id IN ( g.ownerId )
WHERE u.active='1' AND g.gid='15';
And the value of g.ownerId in this senerio is '175,178'.
For some reason this only returns the results from the join with ownerId 175. BUT if I manually enter the values ( 175, 178 ) in the IN clause BOTH rows show up. Why isn't it using both values in the ownerId column?
I have tried this to "separate" the values or force a "list" but it didn't work...
SELECT * FROM users u INNER JOIN groups g ON u.id IN ( SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(g.ownerId, ',', 1), ' ', -1) as x,
SUBSTRING_INDEX(SUBSTRING_INDEX(g.ownerId, ',', 2), ' ', -1) as y ) where g.groupId='15'
Has anyone experienced this before or know what to do?
It doesn't work because the in value consists of a list with a single element that happens to have a comma in it. It is equivalent to:
on uid = '175,178'
You can replace the logic with find_in_set():
on find_in_set(uid, g.id) > 0
However, you really should learn about junctions tables and why your data structure is bad, bad, bad:
You are storing numbers as strings.
You have foreign key relationships with no way to declare them.
You are using string operations inappropriately.
Your query cannot make use of an index.
Fix the data structure.

how to fetch table records and store in variable in sql server and extract each record

I have 3 tables
Category(Category_ID,Category_Name,Parent,Category_Tag)
News_Category(ID,News_ID,Category)
News(News_ID,Title,Article,News_Tags)
I want to fetch all Category_Tag from Category Table where News_ID=72. I am using following query in sql server:
DECLARE #cat varchar(100)
SET #cat=(select Category_Tag
from Category
where Category_ID in(
select Category
from News_Category
inner join Category on Category.Category_ID = News_Category.Category
where News_ID=72
)
)
but this query is not working for me it is showing error as:- Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
.Also i want to extract each single record from the above query to update News table column News_Tags.Suppose the News_Tags column in News table contains value "Tejpal" and the above query returning two values- National and Interbational. then the final value should be stored in News_Tags Column of News Table as Tejpal,National,International
Please help me here
The error here is pretty descriptive. You have declared a scalar variable which is designed to hold a single value, and you are trying to insert multiple rows into that variable.
You need to either do one of two things, either use a temporary table such as
DECLARE #Cat TABLE (CategoryTag VARCHAR(1000));
INSERT INTO #Car
SELECT C.Category_Tag
FROM Category C
INNER JOIN News_Category N ON N.Category = C.CategoryID
WHERE N.News_ID = 72
or you can concatenate the values to be a single string.
I think in this case you might be looking for the second option which would look something like this. This code is mostly psuedo taking from another script I have, but it should put you on the right track.
DECLARE #CategoryTags VARCHAR(1000);
SET #CategoryTags = (
SELECT STUFF((
SELECT ISNULL(Category_Tag, 'NullTag')
FROM Category C
INNER JOIN News_Category N ON N.Category = C.CategoryID
WHERE N.News_ID = N1.NewsID
FOR XML PATH (''),TYPE).value('(./text())[1]','VARCHAR (MAX)')
,1,0,'') [Categories]
FROM News_Category N1
WHERE N1.News_ID = 72
UPDATE News_Category
SET NewTags = NewTags + #CategoryTags
WHERE News_ID = 72
This might help you.
DECLARE #combinedString VARCHAR(MAX)
SELECT #combinedString = COALESCE(#combinedString + CHAR(13) + CHAR(10), '') + ISNULL(Category_Tag, 'NullTag')
FROM Category
select #combinedString