I'm making a query that will delete all rows from table1 that has its column table1.id = table2.id
table1.id column is in nvarchar(max) with an xml format like this:
<customer><name>Paulo</name><gender>Male</gender><id>12345</id></customer>
EDIT:
The id column is just a part of a huge XML so the ending tag may not match the starting tag.
I've tried using name.nodes but it only applies to xml columns and changing the column datatype is not a choice, So far this is the my code using PATINDEX
DELETE t1
FROM table1 t1
WHERE PATINDEX('%12345%',id) != 0
But what I need is to search for all values from table2.id which contains like this:
12345
67890
10000
20000
30000
Any approach would be nice like sp_executesql and/or while loop, or is there a better approach than using patindex? thanks!
Select *
--Delete A
From Table1 A
Join Table2 B on CharIndex('id>'+SomeField+'<',ID)>0
I don't know the name of the field in Table2. I am also assuming it is a varchar. If not, cast(SomeField as varchar(25))
EDIT - This is what I tested. It should work
Declare #Table1 table (id varchar(max))
Insert Into #Table1 values
('<customer><name>Paulo</name><gender>Male</gender><id>12345</id></customer>'),
('<customer><name>Jane</name><gender>Femail</gender><id>7895</id></customer>')
Declare #Table2 table (SomeField varchar(25))
Insert into #Table2 values
('12345'),
('67890'),
('10000'),
('20000'),
('30000')
Select *
--Delete A
From #Table1 A
Join #Table2 B on CharIndex('id>'+SomeField+'<',ID)>0
;with cteBase as (
Select *,XMLData=cast(id as xml) From Table1
)
Select *
From cteBase
Where XMLData.value('(customer/id)[1]','int') in (12345,67890,10000,20000,30000)
If you are satisfied with the results, change the final Select * to Delete
Related
Tables have been created and used without and ID column, but ID column is now needed. (classic)
I heard everything could be done without cursors. I just need every row to contain a different int value so I was looking for some kind of row number function :
How do I use ROW_NUMBER()?
I can't tell exactly how to use it even with these exemples.
UPDATE [TableA]
SET [id] = (select ROW_NUMBER() over (order by id) from [TableA])
Subquery returned more than 1 value.
So... yes of course it return more than one value. Then how to mix both update and row number to get that column filled ?
PS. I don't need a precise order, just unique values. I also wonder if ROW_NUMBER() is appropriate in this situation...
You can use a CTE for the update
Example
Declare #TableA table (ID int,SomeCol varchar(50))
Insert Into #TableA values
(null,'Dog')
,(null,'Cat')
,(null,'Monkey')
;with cte as (
Select *
,RN = Row_Number() over(Order by (Select null))
From #TableA
)
Update cte set ID=RN
Select * from #TableA
Updated Table
ID SomeCol
1 Dog
2 Cat
3 Monkey
You can use a subquery too as
Declare #TableA table (ID int,SomeCol varchar(50))
Insert Into #TableA values
(null,'Dog')
,(null,'Cat')
,(null,'Monkey');
UPDATE T1
SET T1.ID = T2.RN
FROM #TableA T1 JOIN
(
SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) RN,
*
FROM #TableA
) T2
ON T1.SomeCol = T2.SomeCol;
Select * from #TableA
I have data that looks like this:
Table_A:
Source tableName systemid
A table_1 123abcA2
B table_1 222DEFD3
C table_1 369CCCB3
Table_B:
Source tableName systemid
Q table_2 123abc
R table_2 222DEF
C table_2 369CCC
I ran the following query:
select a.Source, a.tableName, a.systemid as a_systemid, b.systemid as b_systemid
from table_a as a
inner join table_b as b on a.systemid = b.systemid
Here is what came back:
Source tableName a_systemid b_systemid
A table_1 123abcA2 123abc
B table_1 222DEFD3 222def
C table_1 369CCCB3 369CCC
Shouldn't I get nothing returned? As nothing matches.
Table A system id = nvarchar data type
Table b systemid = uniqueidentifier data type
Implicit casting is occuring and essentially truncating your string data which causes a match. You need to explicitly cast the uniqueidentifier to an nvarchar(max).
Please see this question and answer.
DECLARE #t1 TABLE([Source] CHAR(1),tableName VARCHAR(10),systemid nvarchar(max))
DECLARE #t2 TABLE([Source] CHAR(1),tableName VARCHAR(10),systemid uniqueidentifier)
INSERT INTO #t1 SELECT 'A','table_1','15b993cc-e8be-405d-bb9f-0c58b66dcdfe_1'
INSERT INTO #t1 SELECT 'B','table_1','4cffe724-3f68-4710-b785-30afde5d52f8_1'
INSERT INTO #t1 SELECT 'C','table_1','7ad22838-ddee-4043-8d1f-6656d2953545_1'
INSERT INTO #t2 SELECT 'Q','table_2','15b993cc-e8be-405d-bb9f-0c58b66dcdfe'
INSERT INTO #t2 SELECT 'R','table_2','4cffe724-3f68-4710-b785-30afde5d52f8'
INSERT INTO #t2 SELECT 'C','table_2','7ad22838-ddee-4043-8d1f-6656d2953545'
select a.Source, a.tableName, a.systemid as a_systemid, b.systemid as b_systemid
from #t1 as a
inner join #t2 as b on a.systemid = CONVERT(NVARCHAR(MAX),b.systemid)
As a practice, you should always explicitly cast mismatched datatypes for clarity as well as prevent weird "what is going on?!?!" stuff.
I have a table (Table1) that has 4 columns (ID1, ID2, Percent, Time, Expired). I want to insert a bunch of new rows in that table where ID1 is taken from another SQL query I have and all the other columns are set to some specified values.
So I have my query:
SELECT someID FROM other_tables WITH other_conditions
And essentially what I want to do is
FOR v in <above query>
Insert New row into Table1 (v, some second id, some percent, some time, some expired value)
EDIT I'm not opposed to not doing this in a loop, just don't know what the best way to insert the data is
You can use a cursor and fetch I think for what you are trying to accomplish. Here is a shell for you...
WITH CURSOR
DECLARE c CURSOR FOR
SELECT DISTINCT colName FROM Table1 JOIN Table2 ON <stuff> WHERE <other_stuff>
DECLARE #ID VARCHAR(4) --or what ever is needed
OPEN c
FETCH NEXT FROM c INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO Table1 (ID, ID2, Percent, Time, Expired)
VALUES (#ID, some second id, some percent, some time, some expired value)
WHERE ID = #ID
FETCH NEXT FROM c INTO #ID
END
CLOSE c
DEALLOCATE c
WITH CROSS APPLY (DUMMY DATA)
if object_id('tempdb..#ids') is not null drop table #ids
if object_id('tempdb..#idDetails') is not null drop table #idDetails
create table #ids (id int)
insert into #ids (id) values
(1),(2),(3)
select i.*, d.*
into #idDetails
from #ids i cross apply (select 2 as id2 ,2.0 as per,'1/1/2016' as dt,'x' as x) d
select * from #idDetails
WITH CROSS APPLY (EXAMPLE WITH YOUR TABLES)
select i.someID, d.*
into #idDetails
from other_tables i
cross apply (select 'some second id' as id2 ,'some percent' as [Percent],'1/1/2016 14:55:22' as [SomeTime] as dt,'SomeExpiredVal' as [ExpiredVal]) d
select * from #idDetails
Maybe I am missing something, but you need a table valued function which returns the desired row for each row in Table1
create function fn_get_new_recs(id int)
RETURNS #results TABLE (Id INT,<other columns you need>)
AS
BEGIN
--Query here to return new records for a single id
END
then use CROSS APPLY
INSERT INTO Table1(Id,Col1,Col2,Col3)
SELECT ST.Id,ST.Col1,ST.Col2,ST.Col3
FROM Table1 T
cross apply fn_get_new_recs(T.Id) ST
I have a query that joins a master and a detail table. Master table records are duplicated in results as expected. I get aggregation on detail table an it works fine. But I also need another aggregation on master table at the same time. But as master table is duplicated, aggregation results are duplicated too.
I want to demonstrate this situation as below;
If Object_Id('tempdb..#data') Is Not Null Drop Table #data
Create Table #data (Id int, GroupId int, Value int)
If Object_Id('tempdb..#groups') Is Not Null Drop Table #groups
Create Table #groups (Id int, Value int)
/* insert groups */
Insert #groups (Id, Value)
Values (1,100), (2,200), (3, 200)
/* insert data */
Insert #data (Id, GroupId, Value)
Values (1,1,10),
(2,1,20),
(3,2,50),
(4,2,60),
(5,2,70),
(6,3,90)
My select query is
Select Sum(data.Value) As Data_Value,
Sum(groups.Value) As Group_Value
From #data data
Inner Join #groups groups On groups.Id = data.GroupId
The result is;
Data_Value Group_Value
300 1000
Expected result is;
Data_Value Group_Value
300 500
Please note that, derived table or sub-query is not an option. Also Sum(Distinct groups.Value) is not suitable for my case.
If I am not wrong, you just want to sum value column of both table and show it in a single row. in that case you don't need to join those just select the sum as a column like :
SELECT (SELECT SUM(VALUE) AS Data_Value FROM #DATA),
(SELECT SUM(VALUE) AS Group_Value FROM #groups)
SELECT
(
Select Sum(d.Value) From #data d
WHERE EXISTS (SELECT 1 FROM #groups WHERE Id = d.GroupId )
) AS Data_Value
,(
SELECT Sum( g.Value) FROM #groups g
WHERE EXISTS (SELECT 1 FROM #data WHERE GroupId = g.Id)
) AS Group_Value
I'm not sure what you are looking for. But it seems like you want the value from one group and the collected value that represents a group in the data table.
In that case I would suggest something like this.
select Sum(t.Data_Value) as Data_Value, Sum(t.Group_Value) as Group_Value
from
(select Sum(data.Value) As Data_Value, groups.Value As Group_Value
from data
inner join groups on groups.Id = data.GroupId
group by groups.Id, groups.Value)
as t
The edit should do the trick for you.
I need something like
select * from tb_listings for xml auto
But I need every row to be separate, and not one big xml document.
I have tried something like the following:
select id, (select * from tb_listings a where a.id=id for xml auto) as xmldata from tb_listings
Expected output is like:
id xmldata
------------------------------------------------------------
1 <listing><name>ABC</name><xyz>123</xyz></listing>
But it doesn't seem to do what I want and it also takes a very long time to run.
Any ideas would be appreciated. :)
Edit: Figured it out:
select id, (select top 1 * from tb_listings a where a.id=b.id for xml auto) from tb_listings b
Closing.
try something like this:
DECLARE #YourTable table (PK1 int, c1 int, c2 varchar(5), c3 datetime)
INSERT INTO #YourTable VALUES (1,2,'abcde','1/1/2009')
INSERT INTO #YourTable VALUES (100,200,'zzz','12/31/2009 23:59:59')
--list all columns in xml format
SELECT
t2.PK1 --optional, can remove this column from the result set and just get the XML
,(SELECT
*
FROM #YourTable t1
WHERE t1.PK1= t2.PK1
FOR XML PATH('YourTable'), TYPE
) as Row
FROM #YourTable t2
OUTPUT:
PK1 Row
----------- ------------------------------------------------------------------------------------------
1 <YourTable><PK1>1</PK1><c1>2</c1><c2>abcde</c2><c3>2009-01-01T00:00:00</c3></YourTable>
100 <YourTable><PK1>100</PK1><c1>200</c1><c2>zzz</c2><c3>2009-12-31T23:59:59</c3></YourTable>
(2 row(s) affected)