what's the difference between SQL's - sql

I work with Databases not extensively but to the point where I can write Selects, update's ,small joins etc..
I can get my work done with my current knowledge. I have encountered some difficulty while trying to complete a task, I got the task completed but would like to understand why some of the SQL's that I have written in process did not work.
Task at hand: I have a table "TESTTABLE" that has 5 columns and the 6th is the sum of these 5 columns.
Currently table looks like below:
ID NAME SUB1 SUB2 SUB3 SUB4 SUB5 TOTAL
1 VA 10 20 30 40 50
2 MI 20 40 60 80 10
3 NC 10 30 50 70 90
4 SC 10 20 30 40 50
5 WA 20 40 60 80 15
the last column 'Total' is currently empty.
Now,I need to update the total column in the table with the sum(sub1+sub2=sub3+sub4+sub5).
In this process I have written the following SQL's and it did work, would like to understand the difference.
Attempt1:
UPDATE TESTTABLE T
SET Total =
SELECT (sub1+sub2+sub3+sub4+sub5)
FROM TESTTABLE TB
WHERE T.ID = TB.ID);
Error encountered:--ERROR: (2) This form of correlated query is not supported - consider rewriting;
Attempt2:
CREATE TABLE TEMP_TESTTABLE AS( SELECT ID, SUM(sub1+sub2+sub3+sub4+sub5) AS SUB_TOTAL FROM TESTTABLE )
UPDATE TESTTABLE A
SET TOTAL =
(SELECT SUB_TOTAL
FROM TEMP_TESTTABLE B
WHERE B.ID=A.ID);
ERROR encountered: ERROR: (2) This form of correlated query is not supported - consider rewriting
Attempt3:
UPDATE TESTTABLE
SET TOTAL = SUM(sub1+sub2+sub3+sub4+sub5);
ERROR encountered: ERROR: Aggregate functions not allowed in the set list of an UPDATE statement
Attempt4- Successful one;
UPDATE TESTTABLE A
SET TOTAL = B.SUB_TOTAL FROM TEMP_TESTTABLE B
WHERE A.ID=B.ID
Attempt 4 worked for me by using the temp table created in attempt2 [TEMP_TESTTABLE].
I need some detail explanation, and appreciate if anyone can provide me and let me know how my attempt4 is different than 1,2,3.
Help is greatly appreciated.
Thanks,

Attempt1 failed because subqueries should be enclosed in parentheses.
UPDATE TESTTABLE T
SET Total =
(SELECT (sub1+sub2+sub3+sub4+sub5)
FROM TESTTABLE TB
WHERE T.ID = TB.ID);
Attempt2 failed because SUM() function is aggregate function, to sum values from multiple rows, not to sum values from multiple columns in one row.
You should redefine the column as a computed column, like this
Alter table TESTTABLE
add column Total as sub1+sub2+sub3+sub4+sub5

This is the cannonical Soluion.
UPDATE
TESTTABLE
SET
Total = (sub1+sub2+sub3+sub4+sub5)
The reason the others failed is that you where doing subselects that returned multiple rows. You didn't tell the UPDATE how the different rows mapped from the select to the UPDATE.
In this version you are making it simple - one table - on each row set a value on that row based on the data in that row.
In your final version you're doing the same but in a redundant way (extra join that does nothing).

Related

Sum values of two columns row in SQL

Below is the query I have prepared to fetch the details from the database.
select vUI.ArticleID , vUCS.NumInstalled,vUCS.NumPresent, vUCS.NumPending, vUCS.NumFailed, vUCS.NumNotApplicable , vUCS.NumMissing, vUCS.NumUnknown , vUCS.NumTotal
from v_Update_DeploymentSummary_Live vUCS
inner join v_UpdateInfo vUI
on vUCS.CI_ID=vUI.CI_ID
where vUCS.CollectionID='RA00686' --or vUCS.CollectionID='RA00785'
There are a couple of things I tried to achieve but getting hard time.
Below is the output data.
I am hoping that screenshot should be visible. but in case if its missing I would like to add values of vUCS.NumInstalled and vUCS.NumPresent as both are showing data for success.
How can I add the value of two columns in a row?
My query is little bit slow due to vUCS.CollectionID='RA00686' or vUCS.CollectionID='RA00785', I am trying to change it as it is taking more than 3 minutes to run.
Current Output
ArticleID NumInstalled NumPresent NumPending
4484107 2 16 2
4519998 0 0 0
4521860 7573 7738 13
Expected Output
ArticleID NumInstalled NumPending
4484107 18 2
4519998 0 0
4521860 15311 13
Try the below:
select vUI.ArticleID ,
ISNULL(vUCS.NumInstalled,0)+ISNULL(vUCS.NumPresent,0) AS NumInstalled,
vUCS.NumPending
from v_Update_DeploymentSummary_Live vUCS
inner join v_UpdateInfo vUI
on vUCS.CI_ID=vUI.CI_ID
where vUCS.CollectionID='RA00686'
And you have to create an Index for the vUCS.CollectionID column to increase the query performance.
CREATE NONCLUSTERED INDEX NCX_v_Update_DeploymentSummary_Live_Indx1 ON v_Update_DeploymentSummary_Live(CollectionID)

SQL - Update top n records for each value in column a where n = count of column b

I have one table with the following columns and sample values:
[test]
ID | Sample | Org | EmployeeNumber
1 100 6513241
2 200 3216542
3 300 5649841
4 100 9879871
5 200 6546548
6 100 1116594
My example count query based on [test] returns these sample values grouped by Org:
Org | Count of EmployeeNumber
100 3
200 2
300 1
My question is can I use this count to update test.Sample to 'x' for the top 3 records of Org 100, the top 2 records of Org 200, and the top 1 record of Org 300? It does not matter which records are updated, as long as the number of records updated for the Org = the count of EmployeeNumber.
I realize that I could just update all records in this example but I have 175 Orgs and 900,000 records and my real count query includes an iif that only returns a partial count based on other columns.
The db that I am taking over uses a recordset and loop to update. I am trying to write this in one SQL update statement. I have tried several variations of nested select statements but can't quite figure it out. Any help would save my brain from exploding. Thanks!
Assuming, that id is the unique ID of the row, you could use a correlated subquery to select the count of row IDs of the rows sharing the current organization, that are less than or equal to the current row ID and check, that this count is less than or equal to the number of records from that organization you want to designate.
For example to mark 3 records of the organization 100 you could use:
UPDATE test
SET sample = 'x'
WHERE org = 100
AND (SELECT count(*)
FROM test t
WHERE t.org = test.org
AND t.id <= test.id) <= 3;
And analog for the other cases.
(Disclaimer: I don't have access to Access (ha, ha, pun), so I could not test it. But I guess it's basic enough, to work in almost every DBMS, also in Access.)

SQL Case with calculation on 2 columns

I have a value table and I need to write a case statement that touches 2 columns: Below is the example
Type State Min Max Value
A TX 2 15 100
A TX 16 30 200
A TX 31+ 500
Let say I have another table that has the following
Type State Weight Value
A TX 14 ?
So when I join the table , I need a case statement that looks at weight from table 2 , type and state - compare it to the table 1 , know that the weight falls between 2 and 15 from row 1 and update Value in table 2 with 100
Is this doable ?
Thanks
It returns 0 if there aren't rows in this range of values.
select Type, State, Weight,
(select coalesce(Value, 0)
from table_b
where table_b.Type = table_a.Type
and table_b.State = table_a.State
and table_a.Value between table_b.Min and table_b.Max) as Value
from table_a
For an Alteryx solution: (1) run both tables into a Join tool, joining on Type and State; (2) Send the output to a Filter tool where you force Weight to be between Min and Max; (3) Send that output to a Select tool, where you grab only the specific columns you want; (since the Join will give you all columns from all tables). Done.
Caveats: the data running from Join to Filter could be large, since you are joining every Type/State combination in the Lookup table to the other table. Depending on the size of your datasets, that might be cumbersome. Alteryx is very fast though, and at least we're limiting on State and Type, so if your datasets aren't too large, this simple solution will work fine.
With larger data, try to do it as part of your original select, utilizing one of the other solutions given here for your SQL query.
Considering that Min and Max columns in first table are of Integer type
You need to use INNER JOIN on ranges
SELECT *
FROM another_table a
JOIN first_table b
ON a.type = b.type
AND a.State = b.State
AND a.Weight BETWEEN b.min AND b.max

In VBA Excel through ADO SQL, How may I refer to a record "only once" and link it to another avoiding the same record to be recalled?

I have a table with 3 fields:
(the quantity are positive and negative)
TAB_A
ID | quantity | Related_ID
1 100 *? (It is 2 and it is correct)
2 -100 (nothing)
3 100 *? (It is 2 but it should be 4)
4 -100 (nothing)
and the following SQL query:
UPDATE Table_A AS ta LEFT JOIN Table_A AS tb ON ta.[quantity] = -tb.[quantity]
SET ta.Related_ID = tb.[ID]
WHERE ta.[quantity] > 0 AND tb.[Quantity] < 0
I would like to add to the query a part that recognizes the ID already used and won't use them a second time.
Something like this might help, depending on whether all your data is like the sample you posted.
query from question
and tb.id =
(select min(id)
from table_a
where id > ta.id)
The syntax might not be 100% correct but the logic should be ok. Test this by changing your update query to a select query and look at the results.
This solution is in line with my question but I do not think if it is able to cover all the cases. The initial results can be also listed as follow:
-100
-90
-100
100
90
100
The quantity could be listed in any order randomly.

SQL - How to update a field in a record to summed value from two tables

I'm having a problem getting a table to update and am hoping that maybe someone here can help me out. I'm just learning SQL, so I'm not sure of the best way to do certain processes. I have a value in one of my tables that somehow got out of whack. Now, I need to update it using the original value minus the sum of values in a different table.
Table 1 is ORDER_LINES.
ORDER_NO QTY_ON_ORD ORIG_ORD_QTY
0900476 10 100
Table 2 is INVOICED_LINES.
INV_NO SHIP_QTY ORIG_ORD_NO
000441 20 0900476
000441 25 0900476
000441 15 0900476
000441 10 0900476
Value of ORDER_LINES.QTY_ON_ORD should be:
ORDER_LINES.QTY_ON_ORD =
ORDER_LINES.ORIG_ORD_QTY - SUM(INVOICED_LINES.SHIP_QTY)
WHERE INVOICED_LINES.ORIG_ORD_NO = ORDER_LINES.ORDER_NO
So, the value of ORDER_LINES.QTY_ON_ORD is not correct. The values in these are constantly changing, so I'd like to have a SQL command that I can run to update these on the fly. I've tried many things such as:
UPDATE "ORDER_LINES"
SET QTY_ON_ORD = SELECT (
(SELECT SUM(ORIG_ORD_QTY) FROM "ORDER_LINES" WHERE ORDER_NO = '0900476') -
(SELECT SUM(SHIP_QTY) FROM "INVOICED_LINES" WHERE ORIG_ORD_NO = '0900476')
)
WHERE ORDER_NO = '0900476';
But that doesn't work. The Selects by themselves print out the correct qty in my query, but I can't seem to use that qty in my update.
We're running Pervasive SQL if that makes any difference.