Creating a calculated column that references another calculated column - sql

I'm working in Databricks in SQL and im creating a bunch of columns with long equations, what I would like to do is use the calculated column as a reference/variable in other calculated columns.
EXAMPLE of some code I have:
Select
Premium as Premium,
Premium + B as Premium1,
Premium + B + C as Premium2,
Premium + B + C + D as Premium3
from TABLENAME
What I want to achieve:
Select
Premium as Premium
Premium + B as Premium1,
Premium1 + C as Premium2, (where Premium1 = Premium + B which we created)
Premium2 + D as Premium3
from TABLENAME
Is there a way to do this? Thanks?

You can do it as a chain of CTEs like this:
with
p1 as (
select premium, premium + B as premium1
from tablename
),
p2 as (
select premium, premium1, premium1 + C as premium2
from p1
),
p3 as (
select premium, premium1, premium2, premium2 + D as premium3
from p2
)
select
*
from
p3

Related

How to update table from another table, with 2 columns

I am using SQL Server database and want a way to update MachinesSummary.ShareCount.
Here are my two tables
MachinesSummary
ID Machine1 Machine2 ShareCount
-------------------------------
1 A J NULL
2 K S NULL
3 A E NULL
4 J A NULL
5 Y U NULL
6 S W NULL
7 G A NULL
8 W S NULL
The other table is MachineDetails
ProcessNo Machine
------------------
1 A
1 H
1 W
2 A
2 J
2 W
3 Y
3 K
4 J
4 A
I want to update ShareCount in the MachineSummary table with the count of processes that both Machine1 and Machine2 share.
For record 1 in the MachineSummary table, I want the number of processes both share in MachineDetails which is 1 in this case
While for record 4 the ShareCount is 2
I tried this
UPDATE M
SET ShareCount = COUNT(DISTINCT X.ProcessNo)
FROM
(SELECT ProcessNo, ',' + STRING_AGG(Machine,',') + ',' Machines
FROM MachineDetails
GROUP BY ProcessNo) X
INNER JOIN MachinesSummary M ON X.Machines LIKE '%'+ M.Machine1 + '%'
AND X.Machines LIKE '%'+ M.Machine2 + '%'
But I wonder if there is an easier high performance way
The MachineDetails table has 250 million rows.
Well, I would use a self-join to get the number of combinations:
UPDATE M
SET ShareCount = num_processes
FROM MachinesSummary M JOIN
(SELECT md1.Machine as machine1, md2.Machine as machine2, COUNT(*) as num_processes
FROM MachineDetails md1 JOIN
MachinesDetails md2
ON md1.processno = md2.processno
GROUP BY md1.Machine, md2.Machine
) md
ON md.Machine1 = M.machine1 AND md.Machine2 = M.machine2;
I would use an updatable CTE here:
WITH cte AS (
SELECT Machine, COUNT(*) AS cnt
FROM MachineDetails
GROUP BY Machine
),
cte2 AS (
SELECT ShareCount, COALESCE(t1.cnt, 0) AS m1_cnt, COALESCE(t2.cnt, 0) AS m2_cnt
FROM MachineSummary ms
LEFT JOIN cte t1 ON t1.Machine1 = ms.Machine
LEFT JOIN cte t2 ON t2.Machine2 = ms.Machine
)
UPDATE cte2
SET ShareCount = m1_cnt + m2_cnt;
The logic of the first CTE involving the MachineDetails table is to get the counts for every machine. The second CTE joins this counts CTE to the MachineSummary table twice, once for each of machine 1 and 2. Then, we update this second CTE and assign the sum of counts.

SQL - Updating rows in one table with values from another table - Multiple match

I am trying to append values in my Customer table with data from my Sales table.
The customer can have multiple records in the sales table:
Hereby a joined view:
SalesID CustomerID SalesComment CustomerComment
------------------------------------------------------------
1 14 Com1 Customer Comment 1
2 15 Com2 Customer Comment 2
3 14 Com3 Customer Comment 1
4 14 Customer Comment 1
I want to make an update like this:
UPDATE Customer
SET Customer.ShopBookKommentar = CAST([ShopBookKommentar] AS NVARCHAR(MAX)) +
CAST(CHAR(13) + CHAR(10) + S.Comments AS NVARCHAR(MAX))
FROM Customer C
INNER JOIN Sales S ON S.CustomerID = c.ID
But it's not updating any of the Customer rows where one of the Sales rows comment field is empty ('')
It looks like you are using SQL Server. You need to use the table alias for the update:
UPDATE c
SET ShopBookKommentar = c.ShopBookKommentar + CHAR(13) + CHAR(10) + S.Comments
FROM Costumer C INNER JOIN
Sales S
ON S.CostumerID = c.ID;
You only need the cast() if for some reason the intermediate result isn't big enough. But that shouldn't be a problem.
EDIT:
I am guessing that you actually want to apply multiple comments from different rows of Sales. That is a bit trickier:
UPDATE c
SET ShopBookKommentar = c.ShopBookKommentar + c.somm
FROM (SELECT c.*,
(SELECT CHAR(13) + CHAR(10) + S.Comments
FROM Sales s
WHERE S.CostumerID = c.ID AND
S.Comments IS NOT NULL
FOR XML PATH, TYPE
).value(N'.[1]', N'varchar(max)') as scomm
FROM c
) Costumer C INNER JOIN
(Sales S
ON ;

Grouping data without an aggregate function in SQL

I was wondering if anyone could lend some insight into this problem. I'm managing a number of stock portfolios which must contain the same stocks. I need to design a query that will compare all portfolios against all portfolios and return the stocks that exist in one, but not the other.
For simplicity's sake, let's say I have a table that looks like this:
stock_symbol portfolio
AAPL A
IBM A
MCD A
NFLX A
AAPL B
IBM B
MCD B
FB B
AAPL C
IBM C
MCD C
Ideally, I want the query to return something like this:
p1 p2 stock_symbol
A B NFLX
A C NFLX
B A FB
B C FB
So comparing A to B will return NFLX, while comparing B to A will return FB.
Currently, I've got a query that works with a small number of portfolios, but I'm going to be managing >20 portfolios soon. That's hundreds of comparisons. I want to use GROUP BY, but I don't have an aggregate function.
Any ideas as to what I can do? Thanks!
This type of query doesn't need group by. It needs left join. Here is an example query that should do what you want:
select p1.portfolio, p2.portfolio, p1.stock_symbol
from table p1 left join
table p2
on p1.stock_symbol = p2.stock_symbol and
p1.portfolio <> p2.portfolio
where p2.stock_symbol is null;
EDIT:
That is such a good point that p2.portfolio will be NULL. Here is a better solution:
select p1.portfolio, p2.portfolio, p1.stock_symbol
from (select distinct portfolio from table) p1 cross join
(select distinct portfolio from table) p2 left join
table sp1
on sp1.portfolio = p1.portfolio left join
table sp2
on sp1.stock_symbol = sp2.stock_symbol
where sp2.stock_symbol is null;
Give this a try...
Setup:
select * into #tbla from (
SELECT 'AAPL' stock_symbol, 'A' portfolio union all
SELECT 'IBM ', 'A' union all
SELECT 'MCD ', 'A'union all
SELECT 'NFLX', 'A'union all
SELECT 'AAPL', 'B'union all
SELECT 'IBM ', 'B'union all
SELECT 'MCD ', 'B'union all
SELECT 'FB ', 'B'union all
SELECT 'AAPL', 'C'union all
SELECT 'IBM ', 'C'union all
SELECT 'MCD ', 'C'
)a
Query:
WITH symbols
AS (
SELECT DISTINCT stock_symbol
FROM #tbla
)
,portfolios
AS (
SELECT DISTINCT portfolio
FROM #tbla
)
,mstr
AS (
SELECT *
FROM portfolios A
CROSS JOIN symbols B
)
,interim
AS (
SELECT *
FROM mstr m
WHERE NOT EXISTS (
SELECT 1
FROM #tbla A
WHERE m.portfolio = A.portfolio
AND m.stock_symbol = A.stock_symbol
)
)
SELECT A.portfolio
,b.portfolio
,b.stock_symbol
FROM interim A
CROSS JOIN interim B
WHERE A.portfolio <> B.portfolio
AND A.stock_symbol <> B.stock_symbol
Result:
portfolio portfolio stock_symbol
A B NFLX
A C NFLX
B A FB
B C FB
C B NFLX
C A FB

Can someone explain me what is the difference between union All and join in oracle SQL

I am searching for this question since last 2 days what is the difference between UNION and JOIN. Specifically UNION ALL and Natural JOIN.
So I have 2 queries here
first one is
CREATE OR REPLACE VIEW VU_m1 AS
SELECT department_id,manager_id FROM employees
NATURAL JOIN departments ;
SELECT * FROM vu_m1;
and the second one is
CREATE OR REPLACE VIEW VU_m2 AS
SELECT department_id,manager_id FROM employees
UNION ALL
SELECT department_id,manager_id FROM departments;
SELECT * FROM vu_m2;
The result from both the query is exactly same.
So now what is the difference between UNION ALL and Natural JOIN
Details:
I am using Oracle 11gR2 working on Sample HR database.
This is my 2 cents
+----------------------------------+--------------------------------------------+
+- UNION +- JOIN +
+----------------------------------+--------------------------------------------+
+SELECT 1 AS bah FROM DUAL + SELECT * +
+ EMP.DEPTNO + FROM +
+SELECT 2 AS bah FROM DUAL; + (SELECT 1 AS bah from dual) foo +
+ + JOIN +
+ + (SELECT 2 AS bah from dual) bar +
+ + ON 1=1; +
+----------------------------------+--------------------------------------------+
+- RESULTS +
+----------------------------------+--------------------------------------------+
+This gives everything in vertical + This gives everything in horizontal +
+ BAH + BAH BAH +
+ 1 + 1 2 +
+ 2 + +
+----------------------------------+--------------------------------------------+
+- OBSERVATIONS +
+----------------------------------+--------------------------------------------+
+ UNION puts lines from queries + JOIN makes a Cartesian product +
+ after each other + and subsets it +
+ + +
+ UNION combines the results of + JOIN can retrieve data from two or +
+ two or more queries into a single+ more tables based on logical relationships +
+ result set that includes all the + between the tables. Joins indicate how SQL +
+ rows that belong to all queries + should use data from one table to select +
+ in the union. + the rows in another table. +
+ + +
+ UNION makes two queries look + JOIN examine two or more tables in +
+ like one. + a single query statement +
+ + +
+ UNION returns the results of two + JOIN relates similar data in different +
+ different queries as a single + tables. +
+ recordset. + +
+ + +
+----------------------------------+--------------------------------------------+
JOIN picks fields from table A and fields from table B and put all of them together, JOIN is "horizontal" for example:
SELECT A.A1, A.A2, A.A3, B.B1, B.B2
FROM A
INNER JOIN B
ON A.A10 = B.B20
which can be written also like:
select A1, A2, A3, B1, B2 from TABLEA, TABLEB
WHERE A10 = B20
result:
Field-A1 | Field-A2 | Field-A3 | Field-B1 | Field-B2 |
...
UNION/UNIONALL:
Difference between the two is that UNION returns only distinct results while UNIONALL returns ALL the results (including duplicates). UNION/UNIONALL combines the results of two selects - but there's a "catch" - the column-names must be exactly the same - this property make UNION "vertical", for example:
Select A1 as X1, A2 as X2 from TABLEA
UNIONALL
Select B1 as X1, B2 as X2 from TABLEB
result:
Field-X1 | Field-X2
A1 | A2
B1 | B2
...
join:
A join is an SQL operation performed to establish a connection between two or more database tables based on matching columns, thereby creating a relationship between the tables. Most complex queries in an SQL database management system involve join commands.
e.g:
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
The UNION operator is used to combine the result-set of two or more SELECT statements.
Notice that each SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types. Also, the columns in each SELECT statement must be in the same order
syntax:
SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2;

SQL select from table with inner join on itself

I have a table (a view, actually)
id INTEGER, x1 INTEGER, y1 INTEGER, x2 INTEGER, y2 INTEGER
Now I need to select id of all lines, for which the sum of all values in that row with one given row is below zero,
x1 + y1 + x2 + y2 + x3 + y3 + x4 + y4 < 0
Actually I have more complicated formulae, but it doesn't matter now. I understand that I must create INNER JOIN of this table with itself, but still can't compose the right expression.
I use SQLite + Python, if matters. It is about 100 000 rows in table and a valid result can be from all to none.
If I understand correctly what you're after, than something like this should do it:
SELECT a.id
FROM mytable a
JOIN mytable b ON b.id=some_special_value
WHERE a.x1 + a.x2 + a.y1 + a.y1 + b.x1 + b.x2 + b.y1 + b.y2 < 0
You need to get the next row. Let me assume this is the smallest id greater than the id for a given row. The following calculates the next id using a correlated subquery and then joins in the information for the next row:
select *
from (select t.*,
(select t2.id from t t2 where t2.id > t.id order by t2.id limit 1
) nextId
from t
) t left outer join
t tnext
on t.nextId = tnext.Id
where (t.x1 + t.y1 + t.x2 + t.y2) + (tnext.x1 + tnext.y1 + tnext.x2 + tnext.y2) < 0
You can then access the fields from t and tnext.
If you know that the next row has an id exactly 1 greater than its previous row, then you can simplify this to:
select *
from t left outer join
t tnext
on t.id + 1 = tnext.id
where (t.x1 + t.y1 + t.x2 + t.y2) + (tnext.x1 + tnext.y1 + tnext.x2 + tnext.y2) < 0