UPDATE with JOIN not SELECTing expected value - sql-update

I'm trying to UPDATE a temporary transaction table with values from a holdings table. The fields I want to get are from the holding with the lowest date that is higher than the transaction date.
When I use below SELECT statement, the right values are shown:
SELECT h.*
FROM transaction_tmp tt
JOIN holdings h
ON tt.isin = h.isin
AND tt.portfolio = h.portfolio
WHERE h.start_date > tt.tr_date
ORDER BY h.start_date
LIMIT 1
However, when I use below UPDATE statement, incorrect values are selected/updated in transaction_tmp:
UPDATE transaction_tmp tt
JOIN holdings h
ON tt.isin = h.isin
AND tt.portfolio = h.portfolio
SET
tt.next_id = h.id,
tt.next_start_date = h.start_date
WHERE h.start_date > tt.tr_date
ORDER BY h.start_date
LIMIT 1
I'm thinking the WHERE statement is not working appropriately, but unfortunately I cannot figure out how to fix it.
Appreciate any help here!
-Joost

should work using a subquery
UPDATE transaction_tmp tt
JOIN (
SELECT h.*
FROM transaction_tmp tt
JOIN holdings h
ON tt.isin = h.isin
AND tt.portfolio = h.portfolio
WHERE h.start_date > tt.tr_date
ORDER BY h.start_date
LIMIT 1
) tx on ON tt.isin = tx.isin
AND tt.portfolio = tx.portfolio
SET
tt.next_id = tx.id,
tt.next_start_date = tx.start_date

I'm surprised your syntax works. The MySQL documentation is pretty clear that LIMIT and ORDER BY are only allowed when there is a single table reference:
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET assignment_list
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
They are not allowed for the multiple table version of UPDATE:
UPDATE [LOW_PRIORITY] [IGNORE] table_references
SET assignment_list
[WHERE where_condition]
. . .
For the multiple-table syntax, UPDATE updates rows in each table named in table_references that satisfy the conditions. Each matching row is updated once, even if it matches the conditions multiple times. For multiple-table syntax, ORDER BY and LIMIT cannot be used.
I get an error if I try such syntax.

Related

Show all rows as default in calendar in Oracle Apex

I'm creating a report table type calendar where users can create back up by date select a filter that would filter out the table values depending on the user selected. (i.e. if they choose user1, then only back ups with user1 will show up)
I would like it to be when P106_BACK_UP_BY_USER = 0, the table shows all the values (aka getting rid of the "where" portion of the query.
Thank you for your help!
I'm having issues with trying to allow the user to see all the back ups of the table again (getting rid of the filtered value). My current query is this:
I would like it to be when P106_BACK_UP_BY_USER = 0, the table shows all the values (aka getting rid of the "where" portion of the query.
Thank you for your help!
You can use case when statements in your query's where condition as follows:
select *
from my_table
where my_table.created_by =
(select user_name from my_table2 where app_users_id =
case :P106_BACKUP_BY_USER when 0 then app_users_id
else :P106_BACKUP_BY_USER
end)
And for getting better help, please paste your code as text not as an image next time.
This should work too:
...
WHERE b.active_server = s.server_id
AND (:P106_BACK_UP_BY_USER = 0 OR
UPPER(b.created_by) =
(SELECT UPPER(user_name)
FROM eba_bt_app_users
WHERE app_users_id = :P106_BACK_UP_BY_USER
)
);

How do i update sql value with sum comparison

I am trying to update a value to show the picked status of an order based on the picked status against the order qty. The data is in the same table but i cannot figure out the correct syntax. I tried:
Update Orders set Status = 'FULL' where Sum(Qty_Order) = sum(Qty_Picked)
How can i apply this logic using an aggregate query?
Thanks in advance for any help/
One approach uses an update join:
UPDATE Orders o1
INNER JOIN
(
SELECT id
FROM Orders
GROUP BY id
HAVING SUM(Qty_Order) = SUM(Qty_Picked)
) o2
ON o2.id = o1.id
SET
Status = 'FULL';
This assumes that your Orders table has a column id which uniquely identifies each order.

IF condition in DAX is creating Cartesian Join on rows

Dax formula without If condition works fine, but as soon as I add an IF condition rows start multiplying. I believe it's doing Cartesian Product.
My requirement is simple. I need to show only those rows in which Sickness[Start_Date]>LASTDATE(Test[Date])
The complete formula is -
Measure =
var val = CALCULATE(MAX(Sickness[Start_Date]),FILTER(Sickness,Sickness[Start_Date]>LASTDATE(Test[Date])),ALL())
return
IF(val = BLANK(),0,1)
I have 3 separate tables Emp_data, Test and Sickness.
To replicate this scenario, Please follow the below steps:
1st Step : Create table Emp_data
Emp_data = DATATABLE("Emp_no",INTEGER,"Name",STRING,{{101,"A"},
{102,"B"},
{103,"C"},
{104,"D"},
{105,"E"},
{106,"F"},
{107,"G"},
{108,"I"},
{109,"J"},
{110,"K"},
{111,"L"},
{112,"N"},
{113,"M"},
{114,"O"},
{115,"P"},
{116,"Q"},
{117,"R"},
{118,"S"},
{119,"T"},
{120,"U"}
})
create table : Test
Test = DATATABLE("Emp_No",INTEGER,"Date",DATETIME,"Result",INTEGER,{{101,"3/10/2020",1},
{101,"3/13/2020",2},
{102,"3/11/2020",1},
{103,"3/12/2020",2},
{104,"3/13/2020",1},
{105,"3/14/2020",1},
{106,"3/15/2020",2},
{107,"3/16/2020",1},
{108,"4/20/2020",1},
{109,"4/21/2020",2},
{110,"4/22/2020",2},
{111,"4/23/2020",1},
{112,"4/24/2020",1},
{113,"4/25/2020",2},
{114,"4/26/2020",1},
{115,"4/27/2020",2},
{116,"5/5/2020",1},
{117,"5/5/2020",1},
{118,"5/5/2020",1},
{119,"5/5/2020",1},
{120,"5/5/2020",2}
})
Create table Sickness
Sickness = DATATABLE("Emp_no",INTEGER,"Start_Date",DATETIME,"End_Date",DATETIME,"Sickness_Code",INTEGER,{{101,"2/12/2020","2/12/2020",30},
{101,"3/10/2020","3/15/2020",50},
{101,"3/20/2020","3/30/2020",50},
{101,"4/5/2020","4/10/2020",40},
{102,"3/11/2020","3/11/2020",50},
{107,"3/1/2020","3/2/2020",30},
{107,"3/15/2020","3/20/2020",50},
{107,"3/21/2020","3/31/2020",40},
{112,"4/20/2020","4/30/2020",50},
{112,"5/1/2020","5/15/2020",50},
{116,"4/1/2020","4/15/2020",30},
{116,"5/3/2020","5/15/2020",50},
{116,"5/16/2020","5/26/2020",50},
{116,"5/27/2020","5/29/2020",40}}
)
Second Step is to create relationship between these 3 tables. Emp_Data and Test table have one to many relationship. I changed the filter direction to BOTH. Thinking may be this will resolve the issue. Create relation many to many between the tables Test and Sickness. The image is attached
The output is as follows :
If I remove the IF condition my out is what I need :
Can someone help me in understanding this behavior of Power BI. This looks very strange. Why row count is increasing after applying IF condition. Thanks in advance
It's because you assigned a 0 value to all blank values in your Sickness data table. Once your remove the if statement, Power BI only shows data rows that do not return a blank value.
To fix your issue try this updated meassure:
Measure =
VAR val = CALCULATE(MAX(Sickness[Start_Date]),FILTER(Sickness,Sickness[Start_Date]>LASTDATE(Test[Date])),ALL())
VAR OneZero = IF(ISBLANK(val),0,1)
RETURN
IF(HASONEVALUE(Sickness[Emp_no],OneZero)

Power BI - Creating a calculated table

I am creating a dashboard in Power BI. I have to report the executions of a process in a daily basis. When selecting one of these days, I want to create another calculated table based on the day selected (providing concrete information about the number of executions and hours) as it follows:
TABLE_B = FILTER(TABLE_A; TABLE_A[EXEC_DATE] = [dateSelected])
When [dateSelected] is previously calculated from the selected day as it follows:
dateSelected = FORMAT(FIRSTDATE(TABLE_A[EXEC_DATE]);"dd/MM/yyyy")
I tried a lot of alternatives as, for example, create individualy the year, month and day to later compare. I used the format in both sides of the comparation, but none of them works for me. The most of the cases it returns me the whole source table without any kind of filters. In other cases, it doesn't return anything. But, when I put a concrete day ...
TABLE_B = FILTER(TABLE_A; TABLE_A[EXEC_DATE] = "20/02/2019")
... it makes the filter correctly generating the table as I want.
Does someone know how to implement the functionality I am searching for?
Thanks in advance.
You're almost there Juan. You simply need to use dateSelected as a varialbe inside of your DAX query:
TABLE_B =
var dateSelected = FIRSTDATE(TABLE_A[EXEC_DATE])
return
FILTER(TABLE_A, TABLE_A[EXEC_DATE] = dateSelected)
Note that all my dates are formatted as Date so I didn't need to use a FORMAT function.
Here's the final result:
I admit that this behavior can be quite confusing! Here is a useful link that will help you understand Power BI's context:
https://community.powerbi.com/t5/Desktop/Filtering-table-by-measures/td-p/131361
Let's treat option 1 as FILTER(TABLE_A; TABLE_A[EXEC_DATE] = "20/02/2019") and option 2 as FILTER(TABLE_A; TABLE_A[EXEC_DATE] = [dateSelected]). Quote from the post:
In option 1, in the filter function, you are iterating
over each row of your 'Table' (row context). In option 2, because you
are using a measure as part of the filter condition, this row context
is transformed into an equivalent filter context (context transition).
Using variables (...) is very convenient when you want to filter
a column based on the value of a measure but you don't want context
transition to apply.

SQL Update From Where Query

I have 2 tables with information in them. I need to update the SelfServiceUserName column in table A_CLIENT with the value from the SubstVarValue column of the A_DEV_SUBSTVAR_VALUE table when the ClientUID and DeviceID match and the SubstVarName from the A_DEV_SUBSTVAR_VALUE table = samaccount name. Here is the query I've tried to run but I keep getting errors:
UPDATE A_CLIENT
SET SelfServiceUserName = (SELECT SubstVarValue
FROM A_DEV_SUBSTVAR_VALUE
WHERE A_DEV_SUBSTVAR_VALUE.SubstVarName = 'samaccountname')
WHERE A_CLIENT.ClientUID = A_DEV_SUBSTVAR_VALUE.DeviceID
I always write a join between the two tables first to get the rows I want side by side and make sure I have the JOIN clause correct.
SELECT p.ProductID, p.ProductName, p.Price AS OldPrice, n.Price as NewPrice
FROM Products as p
JOIN NewPrices as n on p.ProductID = n.ProductID
Once I have done that it's easy to change it into an update statement by replacing the SELECT clause with an UPDATE and SET:
UPDATE p
SET Price = n.Price
FROM Products as p
JOIN NewPrices as n on p.ProductID = n.ProductID
Note you don't alias the Price on the left side of the SET clause, because it is necessarily from the p (Product) table, so there is no ambiguity. You must still alias the Price on the right of the equals because it could be the field coming from either the p (Product) or n (NewPrice) table.
You could also use a CTE (Common Table Expression) if your SQL engine supports it:
WITH x AS (
SELECT p.ProductID, p.ProductName, p.Price AS OldPrice, n.Price as NewPrice
FROM Products as p
JOIN NewPrices as n on p.ProductID = n.ProductID
)
UPDATE x set OldPrice = NewPrice
Try something like
update a_client c
inner join a_dev_substvar_value d on
c.clientuid = d.deviceid
set
c.selfserviceusername = d.substvarvalue
where
d.substvarname = 'samaccountname';
Note, you should try avoid writing select statements in your were clause because it is run for ever row returned. This can be a big performance hit.
That should work.