sql query to with insert select - sql

I have a table with the below format:
ID curr Date Bid Ask
1 AUD/NZD 20090501 00:00:00.833 1.2866 1.28733
2 AUD/NZD 20090501 01:01:01.582 1.28667 1.2874
3 AUD/NZD 20090501 02:01:01.582 1.28667 1.28747
Now I need to select the change of Bid and Ask column and store into a different table...The result should be like the following
Bid Change Ask Change
0.0000700 0.0000700
0.0000000 0.0000700
select
t1.id,
t1.curr,
t1.date,
t1.bid,
t1.bid - t2.bid [Bid Change],
t1.ask,
t1.ask - t2.ask [Ask Change]
from tbltest t1
left join tbltest t2 on t1.ID = t2.ID + 1
order by date
This query returns everything correct except the format of Bid Change and Ask Change...like the following
BID Change ASK CHANGE
7.00000000000145E-05 7.00000000000145E-05
Am really clueless on what to do with this situation...any little help will work.
Thanks in advance!

It doesn't seem necessary to me to store them in a different table, you can just calculate them on the fly using APPLY, this way any changes to the underlying data will not cause your change data to be stale:
SELECT T.*,
BidChange = t.Bid - prev.Bid,
AskChange = t.Ask - prev.Ask
FROM T
OUTER APPLY
( SELECT TOP 1 T2.Bid, T2.Ask
FROM T AS T2
WHERE T2.Curr = T.Curr
AND T2.Date < T.Date
ORDER BY T2.Date DESC
) AS prev;
If this is something you will need regularly then you may want to consider a view, rather than storing it in a table.

Related

sql nested selects

I'm new to sql and I understand what's going on here in general, but I can't explain it in detail.
I thought ,
The lookupweekid value taken from the lookupday table is decreased by -1 and assigned to the lookupweekid of the t2 table. Where t1.lookupweekid=t2.lookupweekid and t1.weekdaynumber=1. start_of_week is imported into table t3.
What do you think about my thought, is it true?
(select dateoftransaction
from lookupday t1,
(select lookupweekid-1 from lookupday
where dateoftransaction = date) t2 (lookupweekid)
where t1.lookupweekid=t2.lookupweekid
and t1.weekdaynumber=1) t3 (start_of_week)
I'm guessing it's calculating the start of the previous week.
Maybe the t3 sub-query can also be written like this:
select dateoftransaction
from lookupday
where lookupweekid in (select lookupweekid - 1
from lookupday
where dateoftransaction = current_date)
and weekdaynumber = 1

TSQL Repeat values on outer join

I've been working on this for some time now and I would like to get some help.
My database is SQL Server 2008 R2 ( I know, very old).
I basically have a transaction table that captures values per week, by job.
I would like to repeat the last value of a job until it finds the next value.
I have included some data from my table. The last column (values needed) is what I'm trying to achieve.
Thank you very much.
Bruce
image of data
I've tried the SQL below, but it is not giving the correct values. Please see the attachment.
SQL
select t.*, t2.percentcomp as value_needed
from #1 t
outer apply
(select top 1 t2.*
from #1 t2
where t2.job_skey = t.job_skey and
t2.COST_CODE_SKEY=t2.COST_CODE_SKEY and
t2.period_end_date <= t.period_end_date and
t2.percentcomp is not null
order by t.JOB_SKEY,t.phase,t.period_end_date desc
) t2
Attachment..view of SQL. Value_needed should begin with 5
You can do what you want using OUTER APPLY:
select t.*, t2.percent_comp as value_needed
from t outer apply
(select top 1 t2.*
from t t2
where t2.job_skey = t.job_skey and
t2.period_end_date_id <= t.period_end_date_id and
t2.percentcomp is not null
order by t2.period_start_date desc
) t2;
enter image description here

Select left 10 numbers, left join for a price from second table, and then sum, SQL

I am currently working in sql 2012 visual management studio. I have two tables. Table1 has three columns (ItemNumber as varchar, Quantity as int, and TimeOrdered as datetime). Table2 has 2 columns (ItemNumber as varchar, and Price as float). Please note these item numbers are not the same, the part numbers on table 1 have a letter after the number while the table 2 item number does not. For example on table 1 the item number will look something like this 999999999-E and the other table will just be 999999999-. Therefore I must use a select Left for 10 digits to get the part number.
I need to pull a list of item numbers from table 1 based on the time ordered and then cross compare that list to table 2 and multiple the price times the quantity for a grand total. Here is my code so far:
SELECT sum(tbl.quantity * table2.price) as grandtotal,
tbl.PartNumber,
tbl.quanity,
table2.price
FROM
(SELECT left(itemnumber, 10) as itemnumber, quantity
FROM table1
WHERE TimeOrdered between
('2014-05-05 00:00:00.000')
AND
('2015-05-05 00:00:00.000')) as tbl
Left table2 on
tbl.partnumber =tbl2.itemnumber
I am receiving an error here for aggregate columns but I am not sure this is the correct way to go about this to begin with.
-------------update---------------
I got it working. Sorry for taking so long to get back to you guys, I was stuck in a meeting all day,
How About This. The case is just to avoid div by Zero errors.
SELECT sum( Isnull(tbl.quantity,0) * Isnull(table2.price,0) ) as grandtotal,
tbl.PartNumber,
Sum(tbl.quanity),
case when Isnull(Sum(tbl.quanity),0) = 0 then null else
sum(Isnull(tbl.quantity,0) * Isnull(table2.price,0) ) / Sum(tbl.quanity) end
as Price
FROM
(SELECT left(itemnumber, 10) as itemnumber, quantity FROM table1 WHERE TimeOrdered between
('2014-05-05 00:00:00.000')
AND ('2015-05-05 00:00:00.000')) as tbl
Left outer join table2 on
tbl.partnumber =tbl2.itemnumber
group by tbl.PartNumber
SQL server requires you to explicitly group by the columns you're not aggregating by. So you need to add group by tbl.PartNumber, tbl.quantity, table2.price. Of course, that's probably going to make the tbl.quantity * table2.price kind of useless. What are you actually trying to do? :)
Here is a fiddle with some sample data that should give you what you want. You need to include any non-aggregate columns in your group by.
Your code ends up as follows:
SELECT left(table1.ItemNumber, 10) as PartNumber,
table2.price,
sum(table1.quantity) as totalquantity,
sum(table1.quantity * table2.price) as grandtotal
FROM table1
INNER JOIN table2 ON left(table1.ItemNumber, 10) = table2.ItemNumber
WHERE t1.Timerordered BETWEEN '2014-05-05 00:00:00.000' AND '2015-05-05 00:00:00.000'
GROUP BY table1.ItemNumber, table2.price
SQL Fiddle Example
SELECT SUM(t1.quantity * t2.price) AS 'GrandTotal'
,SUM(t1.quantity) AS 'Quantity'
,t1.itemnumber
,t2.price
FROM Table1 t1
JOIN Table2 t2 ON LEFT(t1.itemnumber, 10) = t2.itemnumber
WHERE t1.Timeordered BETWEEN '2014-05-05 00:00:00.000' AND '2015-05-05 00:00:00.000'
GROUP BY t1.itemnumber, t2.price

Only check max date for specific rows?

Edit: Realized there's tons of these questions. Trying a subquery and looking through those.
Edit2: Just needed a subquery. Works now. For the sake of anyone else looking at this, I added
where t2.startdate = (select max(startdate) from table2 as sub
where sub.item = t1.item)
and t1.effectivedate = (select max(startdate) from table2 as sub2)
I'm currently writing a query to pull two rates from two separate tables, and return the difference between the two rates. I'm having trouble with getting the proper rates. I need to only get the rates for the most recent listing for each item. My data in the tables looks like this:
todate item rate
2014-01-15 pencil -0.07
2014-01-17 pencil -0.03
2014-02-22 pencil -0.05
2014-01-15 pen -0.013
2014-01-17 pen -0.02
2014-02-22 pen -0.032
I want it to return this (assuming both tables are exactly the same):
Item Rate1 Rate2 Difference Date
Pencil -0.05 -0.05 0 2014-02-22
Pen -0.032 -0.032 0 2014-02-22
Both tables are more or less the same thing, just with different rates. My problem is I end up getting multiple dates regardless of how I change the query.
I have this right now:
use db
select t1.item, t2.Rate as t2Rate, t1.Rate as t1Rate,(abs(t2.Rate) - abs(t1.Rate))
as Dffrnce, t2.startDate
from table2 as t2 join table1 as t1
on t2.item = t1.item
where t2.StartDate = t1.EffectiveDate
group by t1.item, t2.StartDate, t2.Rate, t1.Rate
having t2.StartDate = max(t2.StartDate)
order by t1.item
I'm guessing my problem is stemming from me not checking each item for their max date specifically. But I'm not entirely sure how to do that. I tried using distinct but that returned the same result. Am I missing something obvious? I only want to grab the rates from the most recent date. I've tried joining on the item and max date, a having statement having max(t2.StartDate) = t1.effectivedate but nothing seems to be working.
Just saw your edit that says you got it working. Nice.
You might consider a different way to identify the rows you want to work with.
Which flavor of SQL are you using? Not everything works everywhere.
DECLARE #Rate1 AS TABLE (id INT, rateDate DATE, rate INT)
DECLARE #Rate2 AS TABLE (id INT, rateDate DATE, rate INT)
INSERT INTO #Rate1 (id, rateDate, rate) VALUES (1, '2000-01-01', 1),(1, '2001-01-01', 3),(2, '2000-01-01', 4)
INSERT INTO #Rate2 (id, rateDate, rate) VALUES (1, '2001-01-01', 2),(2, '2002-01-01', 3)
;WITH r1 AS (SELECT *, ROW_NUMBER() OVER(PARTITION BY id ORDER BY rateDate DESC) rn FROM #Rate1)
, r2 AS (SELECT *, ROW_NUMBER() OVER(PARTITION BY id ORDER BY rateDate DESC) rn FROM #Rate2)
SELECT *
FROM r1
INNER JOIN
r2 ON r1.id=r2.id
WHERE r1.rn=1
AND r2.rn=1

update a field based on subtotal from another table

I'm using oracle(10).
I've got two tables as follows:
Table1 (uniq rows):
ID AMOUNT DATE
Table2:
ID AMOUNT1 AMOUNT2 ...AMOUNTN DATE
Table2 is connected many to one to Table1 connected via ID.
What I need is update-ing Table1.DATE with: the last (earliest) date from Table2 where Table1.AMOUNT - SUM(Table2.AMOUNT1) <= 0, when reading table 2 backwards by the Table2.DATE field.
Is there a simple way to do it?
Thanks in advance!
UPDATE: as I see from your answers I had misspecified the question a bit. So here goes a detailed example:
Table1 has:
ID: 1 AMOUNT:100 DATE:NULL
Table2 has (for ID: 1 so ID is not listed in here):
AMOUNT1 DATE
50 20080131
30 20080121
25 20080111
20 20080101
So in this case I need 20080111 as the DATE in Table1 as 50+30+25 => 100.
Based on your revised question, this is a case for using analytic functions.
Assuming you meant >=100 rather than <= 100 as your example implies, and renaming columns DATE to THEDATE since DATE is a reserved word in Oracle:
update table1 set thedate=
( select max(thedate) from
( select id, thedate,
sum(amount1) over (partition by id order by thedate desc) cumsum
from table2
) v
where v.cumsum >= 100
and v.id = table1.id
)
If the 100 means the current value of table1 then change that line to:
where v.cumsum >= table1.amount
First off - your database layout feels severely wrong, but I guess you can't / don't want to change it. Table1 should probably be a view, and Table2 does not make the impression of proper normalization. Something like (ID, AMOUNT_TYPE, AMOUNT_VALUE, DATE) would make much more sense to me.
But to solve your problem (this is T-SQL "UPDATE FROM" syntax, but I think Oracle knows it):
UPDATE
Table1
SET
Date = Table2Aggregate.MinDate
FROM
Table1
INNER JOIN (
SELECT Id, SUM(Amount1) SumAmount1, MIN(Date) MinDate
FROM Table2
GROUP BY Id
) AS Table2Aggregate ON Table1.Id = Table2Aggregate.ID
WHERE
Table1.Amount - Table2Aggregate.SumAmount1 <= 0