TSQL - WHILE LOOP - tsql

WHILE #Suma < #ZalihaVP
begin
Insert into #Promet (Kljuc, Kolicina, Datum, StarostPrometa)
select top 1 m.acKey, anQTY, m.adDate, DATEDIFF(d, m.adDate, getdate())
from tHE_Move m inner join tHE_MoveItem mi
on m.acKey = mi.acKey
where acReceiverStock = 'Y'
and acReceiver = #Skladiste
and acIdent = #Ident
and m.acKey not in(select Kljuc from #Promet)
order by adDate desc
set #Suma = #Suma + (select SUM(kolicina) from #Promet)
if #Suma > #ZalihaVP begin update #Promet set Kolicina = Kolicina - (#Suma - #ZalihaVP) where KLjuc = (select top 1 KLjuc from #Promet order by Datum) end
if #Suma > #ZalihaVP begin set #Suma = #ZalihaVP end
end
This is my WHILE loop, I have problem here.
#ZalihaVP = 92
#Suma = 0
Records of #promet.kolicina are: 40, 50, 50
On third record, #Suma it's greather than #ZalihaVP 40 + 50 + 50 = 140 > #Suma
and third record it's not inserted, but I want them to insert.
How I can send #Suma < #Zaliha on the end after insert?

I think the problem is this row:
set #Suma = #Suma + (select SUM(kolicina) from #Promet)
There you set #Suma to itself plus all kolicina combined.
Maybe it should be:
set #Suma = select SUM(kolicina) from #Promet

Related

Select distinct where any of the filters are true

Hello how do you select distinct rows when any of the filters return true?
Here is my Statement but it is returning a Cartesian result set of many thousands of duplicate rows. I don't want duplicate rows.
SELECT
Distinct
r.DRAWING
, r.[DESC]
, r.CF3 as rCF3
, e.OP_PSI
From thk t
left join eng e on e.DRAWING = t.DRAWING
left join ref r on r.DRAWING = t.DRAWING
where t.SurveyNumber = #SurveyNumber
or CAST(e.L_RATE AS DECIMAL(10,0)) >= 14
or CAST(e.S_RATE AS DECIMAL(10,0)) >= 14
or (YEAR(GETDATE()) - YEAR(e.REPLDATE)) <= 2
or CAST(e.WALL_LOSS AS DECIMAL(10,2)) >= .30
or CAST(e.RMS AS DECIMAL(10,0)) <= 25
or t.CF1 = 'AI'
ORDER BY r.DRAWING;

Postgres DISTINCT Query issue

SELECT DISTINCT "Users"."id" , "Users".name,
"Users"."surname", "Users"."gender",
"Users"."dob", "Searches"."start_date"
FROM "Users"
LEFT JOIN "Searches" ON "Users"."id" = "Searches"."user_id"
WHERE (SQRT( POW(69.1 * ("Users"."latitude" - 45.465454), 2) + POW(69.1 * (9.186515999999983 - "Users"."longitude") * COS("Users"."latitude" / 57.3), 2))) < 20
AND "Users"."status" = true
AND "Users"."id" != 18
AND "Searches"."activity" = \'clubbing\'
AND "Users"."gender" = \'m\'
AND "Users"."age" BETWEEN 18 AND 30
ORDER BY ABS( "Searches"."start_date" - date \'2016-07-07\' )
For some reasons the above query returns the following error:
for SELECT DISTINCT, ORDER BY expressions must appear in select list
I only want to return unique users but I really don't know what's wrong with it.
Thanks for your help
Just doing what the error message says I would include the expression ABS( "Searches"."start_date" - date '2016-07-07' ) in the SELECT list. No need to change your query logic.
absdiffdate can be discarded later when processing the result.
SELECT DISTINCT "Users"."id" , "Users".name,
"Users"."surname", "Users"."gender",
"Users"."dob", "Searches"."start_date",
ABS( "Searches"."start_date" - date '2016-07-07' ) absdiffdate
FROM "Users"
LEFT JOIN "Searches" ON "Users"."id" = "Searches"."user_id"
WHERE (SQRT( POW(69.1 * ("Users"."latitude" - 45.465454), 2) + POW(69.1 * (9.186515999999983 - "Users"."longitude") * COS("Users"."latitude" / 57.3), 2))) < 20
AND "Users"."status" = true
AND "Users"."id" != 18
AND "Searches"."activity" = 'clubbing'
AND "Users"."gender" = 'm'
AND "Users"."age" BETWEEN 18 AND 30
ORDER BY ABS( "Searches"."start_date" - date '2016-07-07' )
Will this new column results in possibly more records when DISTINCT is applied?
I don't think so because you are subtracting a constant from start_date and for similar start_date corresponds similar outcome.
In Postgres, you can use DISTINCT ON to get one row per user id:
SELECT DISTINCT ON (u."id") u."id", u.name, u."surname", u."gender", u."dob", s."start_date"
FROM "Users" u LEFT JOIN
"Searches" s
ON u."id" = s."user_id"
WHERE (SQRT( POW(69.1 * (u."latitude" - 45.465454), 2) + POW(69.1 * (9.186515999999983 - u."longitude") * COS(u."latitude" / 57.3), 2))) < 20 AND
u."status" = true AND
u."id" != 18 AND "Searches"."activity" = \'clubbing\' AND
u."gender" = \'m\' AND
u."age" BETWEEN 18 AND 30
ORDER BY users.id, ABS(s."start_date" - date \'2016-07-07\' );
Notice how table aliases make the query easier to write and to read.

SQL Server select from temp table into another temp table

I have this in a stored procedure:
select * into #temp_UNION from
(
SELECT 6 AS InteractionType, * FROM history.GetHistoryRewardPointsForIncentiveOption (588,1,6)
UNION all
SELECT 8 AS InteractionType, * FROM history.GetHistoryRewardPointsForIncentiveOption (558,1,8)
) a
which gives:
interaction type historyid incentiveprogramid points
6 1 1 50
6 1 4 50
6 1 5 50
8 1 3 100
8 1 4 100
then i have:
select tu.InteractionType,ipc.Name,tu.Points from #temp_UNION tu
inner join Incentive.IncentiveProgramCultures ipc
on tu.IncentiveProgramId = ipc.IncentivePrograms_IncentiveProgramId
inner join Zinc.Users zu
on zu.Cultures_DefaultCultureId = ipc.IncentiveProgramCultureId
where zu.UserId = 588
6 India - Q2 Incentive 50
8 India - Q2 Incentive 100
now i need to make up HintText which is a field in my #CategoriesTable(previously defined) by using the name i got from above and the points
UPDATE #CategoriesTable
SET HintText = CASE WHEN HasAssessment = 1
THEN 'Program ' + tu.name + ' will earn you ' + tu.points
ELSE 'With No Assessment'
END
but i get an error on tu.Name: multi part identifier could not be bound?
how can i achieve? should i make use of another temp table with the 2 rows in it?
here new code:
select * into #temp_UNION from
(
SELECT 6 AS InteractionType, * FROM history.GetHistoryRewardPointsForIncentiveOption (588,1,6)
UNION all
SELECT 8 AS InteractionType, * FROM history.GetHistoryRewardPointsForIncentiveOption (558,1,8)
) a
select tu.InteractionType,ipc.Name,tu.Points,zu.UserId into #temp1 from #temp_UNION tu
inner join Incentive.IncentiveProgramCultures ipc
on tu.IncentiveProgramId = ipc.IncentivePrograms_IncentiveProgramId
inner join Zinc.Users zu
on zu.Cultures_DefaultCultureId = ipc.IncentiveProgramCultureId
where zu.UserId = 588
Select * from #temp1 t
UPDATE #CategoriesTable
SET HintText = CASE WHEN HasAssessment = 1
THEN 'Program ' + t.Name + ' and points = ' + t.Points
ELSE 'With No Assessment'
END
FROM #temp1 t
WHERE t.userId = #CategoriesTable.UserId
DROP TABLE #temp_UNION
DROP TABLE #temp1
SELECT *
FROM #CategoriesTable
im not getting the #CategoriesTable?
You must specify the "tu" alias in the update clause
UPDATE #CategoriesTable
SET HintText = CASE WHEN HasAssessment = 1
THEN 'Program ' + tu.name + ' will earn you ' + tu.points
ELSE 'With No Assessment'
END
FROM #temp_UNION tu
WHERE tu.? = #CategoriesTable.? --JOIN condition

set value from select for few select

I have select, iside select have 2 column. This column must be filled from same select, but I don't want use select twice for it. Is it possoble use select 1 time and after that set second column value from first?
Example:
insert into #temptable from
select
a = (select aa from table1 where quantity > 5)
b = (select aa from table1 where quantity > 5)
I need:
insert into #temptable from
select
a = (select aa from table1 where quantity > 5)
b = {value from a}
Update. I wrote bad example, I need set to BalancePrediction1 and BalancePrediction2 value from Balance
INSERT #tmpBalances
SELECT PA.ContractId AS 'ContractId',
Con.Name AS 'ContractName',
Bal.PortfolioAccountId AS 'PortfolioAccountId',
PA.Name AS 'PortfolioAccountName',
RA.GeneralId AS 'RegisterAccountGeneralId',
Bal.BalanceTypeId AS 'BalanceTypeId',
Bt.Name AS 'BalanceTypeName',
Bt.Type AS 'BalanceTypeType',
Bal.BalanceTimeType AS 'BalanceTimeType',
Bal.InstrumentId AS 'InstrumentId',
Ins.Name AS 'InstrumentName',
Ins.GeneralId AS 'InstrumentGeneralId',
(Bal.Balance -
(
SELECT COALESCE(SUM(Mov.Amount), 0)
FROM trd.Movements AS Mov
WHERE
Bal.InstrumentId = Mov.InstrumentId AND
Bal.PortfolioAccountId = Mov.PortfolioAccountId AND
Bal.BalanceTypeId = Mov.BalanceTypeId AND
Bal.BalanceTimeType = Mov.BalanceTimeType AND
DateDiff(DAY, #Date, Mov.Date) > 0 AND
-- Currency může být null a NULL = NULL nejde
COALESCE(Bal.CurrencyId, -1) = COALESCE(Mov.CurrencyId, -1)
)
) as Balance,
Balance AS 'BalancePrediction1',
Balance AS 'BalancePrediction2',
Bal.CurrencyId AS 'CurrencyId',
Ccy.Code AS 'CurrencyCode',
PA.PositionServiceType 'PositionServiceType',
Ccy.Name 'CurrencyName',
S.Nominal AS 'Nominal',
S.NominalCurrencyId AS 'NominalCurrencyId',
trd.GetCurrencyCode(S.NominalCurrencyId) AS 'NominalCurrencyCode'
FROM trd.Balances AS Bal
JOIN trd.PortfolioAccounts AS PA ON PA.Id = Bal.PortfolioAccountId
JOIN trd.Contracts AS Con ON Con.Id = PA.ContractId
JOIN trd.RegisterAccounts AS RA ON RA.Id = PA.RegisterAccountId
JOIN trd.BalanceTypes AS Bt ON Bt.Id = Bal.BalanceTypeId
JOIN trd.Instruments AS Ins ON Ins.Id = Bal.InstrumentId
LEFT OUTER JOIN trd.Currencies AS Ccy ON Ccy.Id = Bal.CurrencyId
LEFT JOIN trd.SecuritiesView S ON s.Id = Ins.Id AND DateDiff(d, S.ValidFrom, #Date) >= 0 AND (S.ValidTo IS NULL OR DateDiff(d, S.ValidTo, #Date) < 0)
AND S.InstrumentInstrumentTypePriceUnit = 1
You could do an update to the table variable after the insert.
update #tmpBalances
set BalancePrediction1 = Balance,
BalancePrediction2 = Balance
Or you can use cross apply to calculate the sum.
INSERT #tmpBalances
SELECT PA.ContractId AS 'ContractId',
Con.Name AS 'ContractName',
Bal.PortfolioAccountId AS 'PortfolioAccountId',
PA.Name AS 'PortfolioAccountName',
RA.GeneralId AS 'RegisterAccountGeneralId',
Bal.BalanceTypeId AS 'BalanceTypeId',
Bt.Name AS 'BalanceTypeName',
Bt.Type AS 'BalanceTypeType',
Bal.BalanceTimeType AS 'BalanceTimeType',
Bal.InstrumentId AS 'InstrumentId',
Ins.Name AS 'InstrumentName',
Ins.GeneralId AS 'InstrumentGeneralId',
(Bal.Balance - Mov.SumAmount) AS Balance,
(Bal.Balance - Mov.SumAmount) AS 'BalancePrediction1',
(Bal.Balance - Mov.SumAmount) AS 'BalancePrediction2',
Bal.CurrencyId AS 'CurrencyId',
Ccy.Code AS 'CurrencyCode',
PA.PositionServiceType 'PositionServiceType',
Ccy.Name 'CurrencyName',
S.Nominal AS 'Nominal',
S.NominalCurrencyId AS 'NominalCurrencyId',
trd.GetCurrencyCode(S.NominalCurrencyId) AS 'NominalCurrencyCode'
FROM trd.Balances AS Bal
JOIN trd.PortfolioAccounts AS PA ON PA.Id = Bal.PortfolioAccountId
JOIN trd.Contracts AS Con ON Con.Id = PA.ContractId
JOIN trd.RegisterAccounts AS RA ON RA.Id = PA.RegisterAccountId
JOIN trd.BalanceTypes AS Bt ON Bt.Id = Bal.BalanceTypeId
JOIN trd.Instruments AS Ins ON Ins.Id = Bal.InstrumentId
LEFT OUTER JOIN trd.Currencies AS Ccy ON Ccy.Id = Bal.CurrencyId
LEFT JOIN trd.SecuritiesView S ON s.Id = Ins.Id AND DateDiff(d, S.ValidFrom, #Date) >= 0 AND (S.ValidTo IS NULL OR DateDiff(d, S.ValidTo, #Date) < 0)
AND S.InstrumentInstrumentTypePriceUnit = 1
CROSS APPLY (SELECT COALESCE(SUM(Mov.Amount), 0)
FROM trd.Movements AS Mov
WHERE
Bal.InstrumentId = Mov.InstrumentId AND
Bal.PortfolioAccountId = Mov.PortfolioAccountId AND
Bal.BalanceTypeId = Mov.BalanceTypeId AND
Bal.BalanceTimeType = Mov.BalanceTimeType AND
DateDiff(DAY, #Date, Mov.Date) > 0 AND
-- Currency může být null a NULL = NULL nejde
COALESCE(Bal.CurrencyId, -1) = COALESCE(Mov.CurrencyId, -1)
) Mov(SumAmount)
SELECT aa AS a, aa AS b
FROM table1
WHERE quantity > 5
One way;
;with T (value) as (
select aa from table1 where quantity > 5
)
insert into #temptable
select value, value from T

Need to retrieve n-rows that are not at the beginning or in the end of the selected list

I have written sql statement :
select * from (
select count(*) as NumberofSignals,signals.transmitter_account,signals.class,signals.type,signals.signal_mode,
signals.area_id,signals.sector_id,signals.region_info_id,signals.zone_info_id,signals.user_id,signals.device_id,
signals.panel_name,signals.panel_id,signals.sector_name,signals.region_code,signals.area_name,signals.zone_code,
signals.description,signals.transmitter_name,signals.transmitter_id,signals.color,'event' as Event,get_name(signals.id,'event') as event_value,
'packetnumber' as packetnumber,get_name(signals.id,'packetnumber') as packetnumber_value,wm_concat(distinct get_name(signals.id,'repeater')) as repeater,
round(avg(get_name(signals.id,'signallevel'))) as avg_signallevel,min(to_char(signals.signal_forming_time, 'yyyy/mm/dd hh24:mi:ss')) as formingtime,
get_name(signals.id,'address') as address,get_name(signals.id,'username') as username,get_name(signals.id,'chaneltype') as channeltype,
get_name(signals.id,'code') as code,get_name(signals.id,'account') as account
from signals,signal_custom_fields where signals.id = signal_custom_fields.signal_id and
signals.id in (select id from (select id,rownum num from((select signals.id
from signals,signal_custom_fields where signal_custom_fields.field_name = 'event'
and signal_custom_fields.field_value is not null and signals.id = signal_custom_fields.signal_id
and signals.signal_forming_time >= to_date('2011/5/10 14:34:44', 'yyyy/mm/dd hh24:mi:ss')
AND signals.signal_forming_time <= to_date('2011/5/10 15:34:44', 'yyyy/mm/dd hh24:mi:ss'))
intersect (select distinct signals.id from signals,signal_custom_fields
where signal_custom_fields.field_name = 'packetnumber' and signal_custom_fields.field_value is not null
and signals.id = signal_custom_fields.signal_id
and signals.signal_forming_time >= to_date('2011/5/10 14:34:44', 'yyyy/mm/dd hh24:mi:ss')
AND signals.signal_forming_time <= to_date('2011/5/10 15:34:44', 'yyyy/mm/dd hh24:mi:ss')))
order by id desc)) group by 'event',signals.transmitter_account,signals.class,
signals.type,signals.signal_mode,signals.area_id,signals.sector_id,signals.region_info_id,signals.zone_info_id,
signals.user_id,signals.device_id,signals.panel_name,signals.panel_id,signals.sector_name,signals.region_code,
signals.area_name,signals.zone_code,signals.description,signals.transmitter_name,signals.transmitter_id,
signals.color, get_name(signals.id,'event'), 'packetnumber',get_name(signals.id,'username'),
get_name(signals.id,'chaneltype'),
get_name(signals.id,'code'),
get_name(signals.id,'account'), get_name(signals.id,'packetnumber'),get_name(signals.id,'address'),
TO_CHAR(signals.signal_forming_time ,'dd/mm/yyyy hh24'),
TRUNC(to_number(to_char(signals.signal_forming_time ,'mi'))/(30))
order by event)where rownum < 300
and here i get the first 300 rows, but how i need to rewright this statment to retrieve second 300 rows ???
Your query doesn't have the rownum listed in the first nested table. Add a rownum column in the first nested table then you can do a between function in the where clause at the top level:
--create a demo table
DROP TABLE paging_test;
CREATE TABLE paging_test AS
(SELECT rownum x FROM user_tables
);
--count how many records exist (in my case there is 821)
SELECT COUNT(*)
FROM paging_test;
--get the first 300 rows
SELECT *
FROM
(SELECT rownum rn, x FROM paging_test ORDER BY x
) pt
WHERE pt.rn BETWEEN 1 AND 300 ;
--get the next 300 rows
SELECT *
FROM
(SELECT rownum rn, x FROM paging_test ORDER BY x
) pt
WHERE pt.rn BETWEEN 300 AND 600 ;
You might also be interested in my reference:
References:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:948366252775