i have a problem of how to update data from table A to table B and make in horizontal from vertical..example is
Table A ----------- Table B
ID ----- Item ----------- ID ------Item
11--- iPhone4 ----------- 11 ------iPhone4,iPhone4s,iPhone5
11--- iPhone4s
11--- iPhone5
mean that from 3 Rows become 1 rows.
Please help,really noob in this case..
Thanks
Try with this..
Select ID,
Left(Item,Len(Item)-1) As Items
From(
Select distinct T2.ID,
(Select
T1.Item + ',' AS [text()]
From TableA T1
where T1.ID = T2.ID
For XML PATH ('')) [item]
From dbo.TableA T2
) t
Try this..Use GROUP_CONCAT to merge in one row the rows you want to merge.
SELECT ID,GROUP_CONCAT(item)
FROM yourtable
GROUP BY ID;
Related
I have two tables where I want to check if a value exists in the second table.
The problem is that in the second table the group field could either be a individual value or a comma delimited value. I need a query to check if the group value exists in table 2 either as a single value or in a comma delimited value
Table 1
Id
Group
1
Group1
2
Group2
3
Group3
5
Group4
6
Group4
7
Group2
Table 2
Group
Group1, Group2
Group3
The results of the select query would be.
Table 1 Filtered Results
Id
Group
1
Group1
2
Group2
3
Group3
7
Group2
Ideally, you should not store multiple pieces of information in a single column.
But you can solve this in set-based fashion, using STRING_SPLIT in a subquery.
SELECT *
FROM t1
WHERE t1.[group] IN (
SELECT TRIM(s.value)
FROM t2
CROSS APPLY STRING_SPLIT(t2.[group], ',') s
);
db<>fiddle
Maybe this is what you want:
select * from Table1 t1 where exists (
select * from Table2 t2 where t2.[Group] like '%'+t1.[Group]+'%'
)
But be careful!!! "Group" is a keyword in SQL, you should not name a field like that.
UPDATE on Larnu comment:
To avoid Group1 and Group10 match, we can do that:
select * from Table1 t1 where exists (
select * from Table2 t2 where (t2.[Group] like '%'+t1.[Group] or t2.[Group] like '%'+t1.[Group]+',%')
)
Try joining the two tables with a LIKE clause, like this:
DECLARE #t1 TABLE (id INT, [group] VARCHAR(255))
DECLARE #t2 TABLE ([group] VARCHAR(255))
INSERT INTO #t1 VALUES (1,'g1'),(2,'g2'),(3,'g3'),(5,'g4'),(6,'g4'),(7,'g2')
INSERT INTO #t2 VALUES ('g1,g2'),('g3')
SELECT DISTINCT t1.*
FROM #t1 t1 INNER JOIN #t2 t2
ON t2.[group] LIKE '%' + t1.[group] OR t2.[group] LIKE '%' + t1.[group] + ',%'
Result:
id
group
1
g1
2
g2
3
g3
7
g2
UPDATED to accommodate Larnu's comment to Carlos's post
Here is a small simplified snipped of my data
OrderID QTY ItemID ActualQTY(does not exist in database)
1 2 1
2 1 2
3 1 1
4 5 3
Now I need a query that will fill in the ActualQTY based on the ItemID's. So summing total QTY for ItemID 1 = 3, and for ItemID 2 = 1, and last for ItemID 3 = 5
It should look like this
OrderID QTY ItemID ActualQTY
1 2 1 3
2 1 2 1
3 1 1 3
4 5 3 5
The problem is I am new to TSQL and I can't figure out a good way to do this.
--EDIT--
Someone else helped me with this problem and gave this solution which seems like the most efficient solution to me. However this solution doesn't work if you need to apply them to an XSD file in visual studio. So I turned it into a table valued function on the server.
SELECT OrderID, QTY, ItemID, SUM(QTY) OVER(PARTITION BY ItemID) AS ActualQTY
So if this solution doesn't work resort to answers below
You can do this:
SELECT
t2.OrderID,
t2.QTY,
t2.ItemID,
t1.ActualQTY
FROM
(
SELECT
ItemId,
SUM(QTY) AS ActualQTY
FROM tablename AS t1
GROUP BY ItemId
) AS t1
INNER JOIN tablename AS t2 ON t1.ItemId = t2.ItemID;
SQL Fiddle Demo
But if you want to update the column ActualQTY values, not just select, you can do this:
UPDATE t1
SET t1.ActualQTY = t2.ActualQTY
FROM tablename AS t1
INNER JOIN
(
SELECT
ItemId,
SUM(QTY) AS ActualQTY
FROM tablename AS t1
GROUP BY ItemId
) AS t2 ON t1.ItemID = t2.ItemID
SQL Fiddle Demo
SELECT b.OrderID,
b.QTY,
b.ItemID,
a.total_sum AS ActualQTY
FROM (SELECT ItemID,
Sum(QTY) AS total_sum
FROM tablename
GROUP BY ItemID) AS a
INNER JOIN tablename b
ON a.ItemID = b.ItemID
Select t.orderid, t.qty, t.itemid, a.actualq as actualqty
From yourtable t join (
Select sum(qty) as actualq, itemid
From yourtable
Group by itemid) a
On t.itemid = a.itemid
I have two tables with identical definition.
T1:
Name VARCHAR(50)
Qty INT
T2:
Name VARCHAR(50)
Qty INT
This is the data each table has:
T1:
Name Qty
a 1
b 2
c 3
d 4
T2:
Name Qty
a 1
b 3
e 5
f 10
I want to have result which can sum the Qty from both the tables based on Name.
Expected resultset:
Name TotalQty
a 2
b 5
c 3
d 4
e 5
f 10
If am do Left Join or Right Join, it is not going to return me the Name from either of the tables.
What i am thinking is to create a temp table and add these records and just do a SUM aggregate on Qty column but i think there should be a better way to do this.
This is how my query looks like which does not return the expected resultset:
SELECT t1.Name, ISNULL(SUM(t1.Qty + t2.Qty),0) TotalQty
FROM t1
LEFT JOIN t2
ON t1.Name = T2.Name
GROUP BY t1.Name
Can someone please tell me if creating a temp table is OK here or there is a better way to do this?
You can use a full outer join:
SELECT
ISNULL(t1.Name, t2.Name) AS Name,
ISNULL(t1.Qty, 0) + ISNULL(t2.Qty, 0) AS TotalQty
FROM t1
FULL JOIN t2 ON t1.Name = T2.Name
See it working online: sqlfiddle
You can use a UNION ALL to select both tables as one, since they have the same definition. From there, you can nest them as a derived table, and then SUM on that:
SELECT [Name], SUM(Qty) AS TotalQty
FROM (
SELECT [Name], Qty
FROM t1
UNION ALL
SELECT [Name], Qty
FROM t2
) YourDerivedTable
GROUP BY [Name]
This should be simple enough, but somehow my brain stopped working.
I have two related tables:
Table 1:
ID (PK), Value1
Table 2:
BatchID, Table1ID (FK to Table 1 ID), Value2
Example data:
Table 1:
ID Value1
1 A
2 B
Table 2:
BatchID Table1ID Value2
1 1 100
2 1 101
3 1 102
1 2 200
2 2 201
Now, for each record in Table 1, I'd like to do a matching record on Table 2, but only the most recent one (batch ID is sequential). Result for the above example would be:
Table1.ID Table1.Value1 Table2.Value2
1 A 102
2 B 201
The problem is simple, how to limit join result with Table2. There were similar questions on SO, but can't find anything like mine. Here's one on MySQL that looks similar:
LIMITing an SQL JOIN
I'm open to any approach, although speed is still the main priority since it will be a big dataset.
WITH Latest AS (
SELECT Table1ID
,MAX(BatchID) AS BatchID
FROM Table2
GROUP BY Table1ID
)
SELECT *
FROM Table1
INNER JOIN Latest
ON Latest.Table1ID = Table1.ID
INNER JOIN Table2
ON Table2.BatchID = Latest.BatchID
SELECT id, value1, value2
FROM (
SELECT t1.id, t2.value1, t2.value2, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.BatchID DESC) AS rn
FROM table1 t1
JOIN table2 t2
ON t2.table1id = t1.id
) q
WHERE rn = 1
Try
select t1.*,t2.Value2
from(
select Table1ID,max(Value2) as Value2
from [Table 2]
group by Table1ID) t2
join [Table 1] t1 on t2.Table1ID = t1.id
Either GROUP BY or WHERE clause that filters on the most recent:
SELECT * FROM Table1 a
INNER JOIN Table2 b ON (a.id = b.Table1ID)
WHERE NOT EXISTS(
SELECT 1 FROM Table2 c WHERE c.Table1ID = a.id AND c.BatchID > b. BatchID
)
I've got two tables:
TableA
------
ID,
Name
TableB
------
ID,
SomeColumn,
TableA_ID (FK for TableA)
The relationship is one row of TableA - many of TableB.
Now, I want to see a result like this:
ID Name SomeColumn
1. ABC X, Y, Z (these are three different rows)
2. MNO R, S
This won't work (multiple results in a subquery):
SELECT ID,
Name,
(SELECT SomeColumn FROM TableB WHERE F_ID=TableA.ID)
FROM TableA
This is a trivial problem if I do the processing on the client side. But this will mean I will have to run X queries on every page, where X is the number of results of TableA.
Note that I can't simply do a GROUP BY or something similar, as it will return multiple results for rows of TableA.
I'm not sure if a UDF, utilizing COALESCE or something similar might work?
Even this will serve the purpose
Sample data
declare #t table(id int, name varchar(20),somecolumn varchar(MAX))
insert into #t
select 1,'ABC','X' union all
select 1,'ABC','Y' union all
select 1,'ABC','Z' union all
select 2,'MNO','R' union all
select 2,'MNO','S'
Query:
SELECT ID,Name,
STUFF((SELECT ',' + CAST(T2.SomeColumn AS VARCHAR(MAX))
FROM #T T2 WHERE T1.id = T2.id AND T1.name = T2.name
FOR XML PATH('')),1,1,'') SOMECOLUMN
FROM #T T1
GROUP BY id,Name
Output:
ID Name SomeColumn
1 ABC X,Y,Z
2 MNO R,S
1. Create the UDF:
CREATE FUNCTION CombineValues
(
#FK_ID INT -- The foreign key from TableA which is used
-- to fetch corresponding records
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #SomeColumnList VARCHAR(8000);
SELECT #SomeColumnList =
COALESCE(#SomeColumnList + ', ', '') + CAST(SomeColumn AS varchar(20))
FROM TableB C
WHERE C.FK_ID = #FK_ID;
RETURN
(
SELECT #SomeColumnList
)
END
2. Use in subquery:
SELECT ID, Name, dbo.CombineValues(FK_ID) FROM TableA
3. If you are using stored procedure you can do like this:
CREATE PROCEDURE GetCombinedValues
#FK_ID int
As
BEGIN
DECLARE #SomeColumnList VARCHAR(800)
SELECT #SomeColumnList =
COALESCE(#SomeColumnList + ', ', '') + CAST(SomeColumn AS varchar(20))
FROM TableB
WHERE FK_ID = #FK_ID
Select *, #SomeColumnList as SelectedIds
FROM
TableA
WHERE
FK_ID = #FK_ID
END
In MySQL there is a group_concat function that will return what you're asking for.
SELECT TableA.ID, TableA.Name, group_concat(TableB.SomeColumn)
as SomColumnGroup FROM TableA LEFT JOIN TableB ON
TableB.TableA_ID = TableA.ID
I think you are on the right track with COALESCE. See here for an example of building a comma-delimited string:
http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string
You may need to provide some more details for a more precise response.
Since your dataset seems kind of narrow, you might consider just using a row per result and performing the post-processing at the client.
So if you are really looking to make the server do the work return a result set like
ID Name SomeColumn
1 ABC X
1 ABC Y
1 ABC Z
2 MNO R
2 MNO S
which of course is a simple INNER JOIN on ID
Once you have the resultset back at the client, maintain a variable called CurrentName and use that as a trigger when to stop collecting SomeColumn into the useful thing you want it to do.
Assuming you only have WHERE clauses on table A create a stored procedure thus:
SELECT Id, Name From tableA WHERE ...
SELECT tableA.Id AS ParentId, Somecolumn
FROM tableA INNER JOIN tableB on TableA.Id = TableB.F_Id
WHERE ...
Then fill a DataSet ds with it. Then
ds.Relations.Add("foo", ds.Tables[0].Columns("Id"), ds.Tables[1].Columns("ParentId"));
Finally you can add a repeater in the page that puts the commas for every line
<asp:DataList ID="Subcategories" DataKeyField="ParentCatId"
DataSource='<%# Container.DataItem.CreateChildView("foo") %>' RepeatColumns="1"
RepeatDirection="Horizontal" ItemStyle-HorizontalAlign="left" ItemStyle-VerticalAlign="top"
runat="server" >
In this way you will do it client side but with only one query, passing minimal data between database and frontend
I tried the solution priyanka.sarkar mentioned and the didn't quite get it working as the OP asked. Here's the solution I ended up with:
SELECT ID,
SUBSTRING((
SELECT ',' + T2.SomeColumn
FROM #T T2
WHERE WHERE T1.id = T2.id
FOR XML PATH('')), 2, 1000000)
FROM #T T1
GROUP BY ID
Solution below:
SELECT GROUP_CONCAT(field_attr_best_weekday_value)as RAVI
FROM content_field_attr_best_weekday LEFT JOIN content_type_attraction
on content_field_attr_best_weekday.nid = content_type_attraction.nid
GROUP BY content_field_attr_best_weekday.nid
Use this, you also can change the Joins
SELECT t.ID,
t.NAME,
(SELECT t1.SOMECOLUMN
FROM TABLEB t1
WHERE t1.F_ID = T.TABLEA.ID)
FROM TABLEA t;
This will work for selecting from different table using sub query.
I have reviewed all the answers. I think in database insertion should be like:
ID Name SomeColumn
1. ABC ,X,Y Z (these are three different rows)
2. MNO ,R,S
The comma should be at previous end and do searching by like %,X,%