I have a temporary table that hold all items available
#TableA
ItemId ItemName ItemVer
1 Name1 2
2 Name2 9
3 Name3 5
.
.
.
500 Name500 3
I then have another that holds all the dates a Snapshot was taken along with the SnapshotId
CREATE TABLE #tmpSnapshot_Dates(
[SnapshotId] [uniqueidentifier] NOT NULL,
[DateTaken] datetime NOT NULL)
INSERT INTO #tmpSnapshot_Dates SELECT SnapshotId, DateTaken From Snapshot_Info Where DateTaken <= #EndDate
Now for each date in the #tmpSnapshot_Dates table I want to get a count that relates it each Item
SELECT ItemId, Count(*) From Items Where SnapshotId = #SnapshotId
And then update #TableA by adding a column
DECLARE #ColName VARCHAR(100)
SET #ColName = 'Installed ' + CONVERT(Varchar, #DateA, 6)
exec('ALTER TABLE #TableA ADD ['+#ColName+'] int NOT NULL CONSTRAINT [DF_#TableA_Installed on] DEFAULT 0')
And then insert the data into the new column. I then need to repeat this for each date in #tmpSnapshot_Dates
giving a resulting #TableA that looks something like
#TableA
ItemId ItemName ItemVer Installed 01 Jan 12 Installed 07 Feb 12
1 Name1 2 34 33
2 Name2 9 56 59
3 Name3 5 12 26
.
.
.
500 Name500 3 98 106
My questions are
Am I creating a nightmare here by approaching it the wrong way?
How am I best to loop through #tmpSnapshot_Dates and then get the data to create the next column? I always try to avoid cursors but is this one of those situation I need to use one?
There could be 12 columns to add and not every item will be returned for each date.
Definitely it won't be nice, but yes, you need to use cursors and iterate over the #tmpSnapshot_Dates, but if you have the option i suggest you to use a reporting software with the capability to create pivot grids.
Would it not be better to have a separate (temp?) table referencing the ItemId in #TableA eg:
InstalledDate ItemId Count
------------- ------ -----
2012-01-01 1 34
2012-01-01 2 56
2012-01-01 3 12
. . .
. . .
. . .
2012-01-01 500 98
2012-02-07 1 33
2012-02-07 2 59
2012-02-07 3 26
. . .
. . .
. . .
2012-02-07 500 106
Related
At the company where I work we buy the same products from different sellers according to who offers us the better price, and to make the purchase decisions easier I'd like a query that would tell me for each productId, what's the latest price recorded for each seller iD.
I have a table that looks something like this.
purchaseId
productId
price
sellerId
date
1
1
23
1
2021-01-13
2
2
20
1
2021-01-13
3
1
33
2
2021-01-19
4
3
55
2
2021-01-19
5
2
25
1
2021-01-23
6
1
19
3
2021-01-23
7
1
22
1
2021-01-26
8
2
29
2
2021-01-29
I'd like the query to return a table like this, with a column for each sellerID:
productId
priceSellerID1
priceSellerId2
priceSellerId3
1
22
33
19
2
25
19
NULL
3
NULL
55
NULL
There are and could be more and more sellers, this is just a small example.
I want to pull this information to fill a DataGridView in a winforms app, what I thought of first was to populate the DGV with the productIds, and then, for each row pull the information with a query like this for each sellerId:
SELECT price FROM purchase_details
WHERE productId = #productID AND date = (SELECT MAX(DATE) FROM purchase_details WHERE productId = #productID and sellerId = #sellerId)
This takes lot of time to fill in the dgv for just a few ids, so I know it's just not the right way, but unfortunately I can't wrap my head around a query that would gather this information efficiently.
Any information would be greatly appreciated, and if there's way I could improve the question I'd like to know too. Thanks.
Seems like you're looking for Dynamic SQL with a little twist. The subquery src will select the last record per productID and SellerID ordered by date
Example
Declare #SQL varchar(max) ='
Select *
From (
Select top 1 with ties
productID
,Item = concat(''priceSellerID'',sellerId)
,Value = price
From #YourTable
Order by row_number() over (partition by productID,SellerID order by date desc)
) src
Pivot (min([Value]) For [Item] in (' + stuff((Select Distinct ','+QuoteName(concat('priceSellerID',sellerId))
From #YourTable
For XML Path('')),1,1,'') + ') ) p
'
Exec(#SQL);
Results
I would like to take rows with all but one column containing duplicate data and take the one unique field and put it in one row, with the one column being added to. I am creating a table from three different databases to create:
Wk RunOrder Job Number ModelNo .... ItemTag
23 28 1234 abcd 1
23 28 1234 abcd 2
23 28 1234 abcd 3
23 28 1234 abcd 4
12 28 1222 abbd 2
12 28 1222 abbd 4
What I would Like is:
Wk RunOrder Job Number ModelNo .... ItemTag
23 28 1234 abcd 1,2,3,4
23 28 1222 abbd 2,4
the RunOrder and ItemTag columns are from different databases
I was able to get the desired output below using a subquery. I assumed you wanted to keep Wk as part of the grouping.
if OBJECT_ID('tempdb..#temp') is not null
drop table #temp
CREATE TABLE #temp (
Wk int,
RunOrder int,
JobNumber int,
ModelNo VARCHAR(10),
ItemTag VARCHAR(5)
)
insert into #temp values(23,28,1234,'abcd',1)
insert into #temp values(12,28,1234,'abcd',2)
insert into #temp values(23,28,1234,'abcd',3)
insert into #temp values(12,28,1234,'abcd',4)
select distinct Wk,RunOrder,JobNumber,ModelNo,
SUBSTRING(
(
SELECT ','+t1.ItemTag AS [text()]
FROM #temp t1
WHERE t1.Wk = t2.Wk and t1.RunOrder=t2.RunOrder and t1.JobNumber=t2.JobNumber and t1.ModelNo=t2.ModelNo
ORDER BY t1.Wk
FOR XML PATH ('')
), 2, 1000) t
from #temp t2
Another solution you could do is use a derived table.
I need to insert an ID of table 1 in table2. The problem is the fact that the sequential rows in table 1 do not have a sequential Id. (someone have erased some rows, hence no sequential Ids for the sequential rows)
Doing a select * from table 1 results in:
Table 1
Id Value1
------------
2 X
4 Y
10 Z
12 XYZ
14 ZD
121 XD
122 ZS
------------
The desired result of table 2 is:
Id Value1 Value2 Date
-----------------------------------
1 67 2 2018-05-15
2 67 4 2018-05-15
3 67 10 2018-05-15
4 67 12 2018-05-15
5 67 14 2018-05-15
6 67 121 2018-05-15
7 67 122 2018-05-15
------------------------------------
The code to insert values in table 2. I only need table 1 to copy the right Id.
declare #value int
set #value=(select count(*) from table1)
while #value>0
begin
insert into (table2)
values ('67',#HOW_TO_RETRIEVE THE CORRECT ID from TABLE 1?,getdate())
set #value=#value-1
end
of course with #value it will not work, I have tried to use the select clause inside values but to no avail. Thanks.
You do NOT want to use a loop for this type of thing. You can use a select statement in your insert quite easily. Something like this work for you. This is assuming that Id in table2 is an identity. If not we can leverage ROW_NUMBER() to generate sequential values.
insert table2
(
Value1
, Value2
, [Date]
)
select '67'
, Id
, getdate()
from Table1
like this?
alter table2 add id bigint identity(1,1)
;
insert table2 (Value1, Value2, Date)
select '67', ID ,getdate()
from TABLE1
;
insert into table2 (value1, value2, [Date])
select 67, Id, getdate() from table1;
Update the value in the column "distance" of table 1 by finding the distance between center_geom from table2 and home_location from table 3.
Table 1
obu_id end_location trip_id end_loc_adj distance
1 51 1234
2 57 1357 44
2 63 1351
3 21 1212 20
3 23 4313
Table 2
id obu_id center_geom
int int geom
51 2 "0101000020ED0800006DFFCAA2A2553341B20E4717774E0C41"
52 3 "0101000020ED080000AE47E17A35F73341FE65F764723C0841"
57 3 "0101000020ED0800006DFFCAA2A2553341B20E4717774E0C41"
21 4 "0101000020ED080000B81E852BC555334186048C9EB1C21141"
Now, see table 1: If we have any value in end_loc_adj then the column : end_loc_adj has to be used rather end_loc Hint: use if-else.
Column name "end_loc" in table 1 has same values as column "id" in table 2.
Table 3
hhid obu_id home_location
(character Int geometry
varying)
11 1 "0101000020ED08000082E2C7A0B2413341BC5818A21F000941"
15 2 "0101000020ED080000B81E852BC555334186048C9EB1C21141"
17 3 "0101000020ED0800006DFFCAA2A2553341B20E4717774E0C41"
17 4 "0101000020ED080000B81E852BC555334186048C9EB1C21141"
22 7 "0101000020ED080000AE47E17A35F73341FE65F764723C0841"
I have tried the following:
select ST_Distance_Sphere ( ST_AsText(cast(v.house_location AS text)) , ST_AsText(cast(l.center AS text)))
from public.locations l, clean.vehicles v
where l.obu_id=v.obu_id
and l.obu_id=3
but this works manually for single obu_id
I want to complete it in one go using a function.
Please give me some idea about how to do this.
Thanks.
house_loc:=(select house_location from table1 where obu_id=b.obu_id);
house_loc_geom := ST_Transform(house_loc,4269);
IF b.end_location_adj IS null THEN
end_loc:= (select center from table2 where id=b.end_location and obu_id= b.obu_id);
else
end_loc:= (select center from tabl2 where id = b.end_location_adj and obu_id = b.obu_id);
end if;
center_geom:=ST_Transform(end_loc,4269);
UPDATE table 1 set dist_from_home_in_meter=distance
where obu_id=b.obu_id and trip_id=b.trip_id and end_location=b.end_location;
this is close to answer, need some modifications.
I've already searched for my problem, but most of the examples (if not all), have to deal with only one or two tables with a one-to-many relationship between them.
So, here goes my scenario:
My first table is:
OrderID Quantity Price
----------------------------------
18 1000.00 160.00
19 1000.00 40.00
22 1000.00 40.00
23 100.00 500.00
24 10.00 50.00
My second table is:
ExtrasID Name
-------------------
1 Value 1
2 Value 2
3 Value 3
4 Value 4
5 Value 5
I have a many-to-many relationship established between the tables above, so there is a third (joint) table which is as follows:
OrderExtrassID OrderExtras_OrderID OrderExtras_ExtrasID
----------------------------------------------------------------
20 19 2
22 22 3
23 23 2
24 23 5
Now, all I want to achieve is to get a result such as the following:
OrderID Extras
----------------------------
18 NULL
19 Value 2
22 Value 3
23 Value 2, Value 5
24 NULL
There are many examples using XML PATH, PIVOT, CTE etc., but none of these seems to help me with my scenario, or at least I've not managed to study them in depth, in order to get my work done...
Thanks in advance,
I would suggest using For XML to return multiple rows into a single row and then using STUFF to removing the extra comma. Something like this:
SELECT O.OrderId
,STUFF(
(
SELECT ',' + E.Name AS [text()]
FROM OrderExtras OE
Inner Join Extras E
ON E.ExtrasId = OE.OrderExtras_ExtrasID
WHERE O.OrderId = OE.OrderExtras_OrderID
ORDER BY E.Name
FOR XML PATH('')
), 1, 1, '') AS ColList
FROM Orders O
And here is the SQL Fiddle.
Good luck.