Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
What is the accepted practice for indenting SQL statements? For example, consider the following SQL statement:
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
How should this be indented? Many thanks.
SELECT column1
, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
I like to have all "," in front, this way I never search them when an error at line X from the SQL editor.
This is an example for those who do not use this type of writting SQL statement. Both contain an error of a missing comma.
SELECT sdcolumn123
, dscolumn234
, sdcolumn343
, ffcolumn434
, sdcolumn543
, bvcolumn645
vccolumn754
, cccolumn834
, vvcolumn954
, cvcolumn104
FROM table1
WHERE column3 IN
(
...
)
SELECT sdcolumn123, dscolumn234, asdcolumn345, dscolumn456, ascolumn554, gfcolumn645 sdcolumn754, fdcolumn845, sdcolumn954, fdcolumn1054
FROM table1
WHERE column3 IN
(
...
)
I found easier and more quick at the first example. Hope this example show you more my point of view.
SELECT column1, column2
FROM table
WHERE column3 IN (
SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
This is pretty short and easy to read. I'd make adjustments if there were more columns selected or more join conditions.
Not sure there is an accepted practice, but here's now how I'd do it:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2
INNER JOIN
table3
ON table2.column1 = table3.column1
)
I like to have "rivers" of white space in the code. It makes it a little easier to scan.
SELECT column1,
column2
FROM table1
WHERE column3 IN (SELECT column4
FROM table2
JOIN table3
ON table2.column1 = table3.column1);
I like jalbert's form of lining up the keywords on their right. I'd also add that I like the ANDs and ORs on the left (some people put them on the right.) In addition, I like to line up my equals signs when possible.
SELECT column1,
column2
FROM table1, table2
WHERE table1.column1 = table2.column4
AND table1.col5 = "hi"
OR table2.myfield = 678
This is my personal method. Depending on the length of the join condition I sometimes indent it on the line below.
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3
ON table2.column1 = table3.column1 -- for long ones
)
I've written a code standard for our shop that is biased in the extreme towards readability/"discoverability" (the latter being primarily useful in insert-select statements):
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
On more complex queries it becomes more obvious how this is useful:
SELECT
Column1,
Column2,
Function1
(
Column1,
Column2
) as Function1,
CASE
WHEN Column1 = 1 THEN
a
ELSE
B
END as Case1
FROM
Table1 t1
INNER JOIN Table2 t2 ON t1.column12 = t2.column21
WHERE
(
FilterClause1
AND FilterClause2
)
OR
(
FilterClause3
AND FilterClause4
)
Once you move to systems with more than a single join in most of your queries, it has been my experience that using vertical space liberally is your best friend with complex SQL.
SQL formatting is an area where there is a great deal of variance and disagreement... But fwiw, I like to focus on readability and think that whatever you do, consistently conforming to any rules that reduce readability is, as the old cliche goes, a "foolish consistency" ( "Foolish consistency is a hobgoblin for simple minds" )
So, instead of calling them rules, here are some guidelines.
For each Major clause in a SQL statement (Select, Insert, Delete, From, Where, Having, Group BY, Order By, ... I may be missing a few) should be EASILY identifiable. So I generally indent them at the highest level, all even with each other. Then within each clause, I indent the next logical sub structure evenly... and so on.. But I feel free to (and often do) change the pattern if in any individual case it would be more readable to do so... Complex Case statements are a good example. Because anything that requires horizontal scrolling reduces readability enormously, I often write complex (nested) Case expressions on multiple lines. When I do, I try to keep the beginning of such a statement hanging indent based on it's logical place in the SQL statement, and indent the rest of the statement lines a few characters furthur...
SQL Database code has been around for a long time, since before computers had lower case, so there is a historical preference for upper casing keywords, but I prefer readability over tradition... (and every tool I use color codes the key words now anyway)
I also would use Table aliases to reduce the amount of text the eye has to scan in order to grok the structure of the query, as long as the aliases do not create confusion. In a query with less than 3 or 4 tables, Single character aliases are fine, I often use first letter of the table if all ther tables start with a different letter... again, whatever most contributes to readability. Finally, if your database supports it, many of the keywords are optional, (like "Inner", "Outer", "As" for aliases, etc.) "Into" (from Insert Into) is optional on Sql Server - but not on Oracle) So be careful about using this if your code needs to be platform independant...
Your example, I would write as:
Select column1, column2
From table1 T1
Where column3 In (Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
Or
Select column1, column2
From table1 T1
Where column3 In
(Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
If there many more columns on the select clause, I would indent the second and subsequent lines... I generally do NOT adhere to any strict (one column per row) kind of rule as scrolling veritcally is almost as bad for readability as scrolling horizontally is, especially if only the first ten columns of the screen have any text in them)
Select column1, column2, Col3, Col4, column5,
column6, Column7, isNull(Column8, 'FedEx') Shipper,
Case Upper(Column9)
When 'EAST' Then 'JFK'
When 'SOUTH' Then 'ATL'
When 'WEST' Then 'LAX'
When 'NORTH' Then 'CHI' End HubPoint
From table1 T1
Where column3 In
(Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
Format the code in whatever manner makes it the most readable...
If you have a lengthy SQL statement that you'd like to reformat without all the typing and tabbing, you can slap it into this website and get a nicely formatted result. You can experiment with various formats to see which makes your text the most readable.
Edit: I believe that this is the 2014 location of the SQL formatter.
Here's my poke at this:
select column1, column2
from table1
where (column3 in (
select top(1) column4
from table2
inner join table3
on (table2.column1 = table3.column1)
))
;
Everything lowercase because it's easier to read lowercase characters (and we have code highlighting to emphasize keywords) also easier to type
Every restriction or option on a keyword (like the from on the select or the on on the join) is indented to show their dependance on the outward keyword
The closing bracket is at the same indenting level as the opening where
Use brackets for where- and on-clauses to increase readability
Have the semicolon closing the select-statement at the same indenting so multiple statements can be distinguished better (if you need a semicolon in your language like SAS PROC SQL does)
It's still quite compact and does not stretch all over the page
I like to have the different parts of my query line up vertically. I tend to use a tab size of 8 spaces for SQL which seems to work well.
SELECT column1,
column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
Example indenting a very very very complex SQL:
SELECT
produtos_cesta.cod_produtos_cesta,
produtos.nome_pequeno,
tab_contagem.cont,
produtos_cesta.sku,
produtos_kits.sku_r AS sku_kit,
sku_final = CASE
WHEN produtos_kits.sku_r IS NOT NULL THEN produtos_kits.sku_r
ELSE produtos_cesta.sku
END,
estoque = CASE
WHEN produtos2.estoque IS NOT NULL THEN produtos2.estoque
ELSE produtos.estoque
END,
produtos_cesta.unidades as unidades1,
unidades_x_quantidade = CASE
WHEN produtos.cod_produtos_kits_tipo = 1 THEN CAST(produtos_cesta.quantidade * (produtos_cesta.unidades / tab_contagem.cont) * produtos_kits.quantidade AS int)
ELSE CAST(produtos_cesta.quantidade * produtos_cesta.unidades AS int)
END,
unidades = CASE
WHEN produtos.cod_produtos_kits_tipo = 1 THEN produtos_cesta.unidades / tab_contagem.cont * produtos_kits.quantidade
ELSE produtos_cesta.unidades
END,
unidades_parent = produtos_cesta.unidades,
produtos_cesta.quantidade,
produtos.controla_estoque,
produtos.status
FROM
produtos_cesta
INNER JOIN produtos
ON (produtos_cesta.sku = produtos.sku)
INNER JOIN produtos_pacotes
ON (produtos_cesta.sku = produtos_pacotes.sku)
INNER JOIN (
SELECT
produtos_cesta.cod_produtos_cesta,
cont = SUM(
CASE
WHEN produtos_kits.quantidade IS NOT NULL THEN produtos_kits.quantidade
ELSE 1
END
)
FROM
produtos_cesta
LEFT JOIN produtos_kits
ON (produtos_cesta.sku = produtos_kits.sku)
LEFT JOIN produtos
ON (produtos_cesta.sku = produtos.sku)
WHERE
shopper_id = '" + mscsShopperId + #"'
GROUP BY
produtos_cesta.cod_produtos_cesta,
produtos_cesta.sku,
produtos_cesta.unidades
)
AS tab_contagem
ON (produtos_cesta.cod_produtos_cesta = tab_contagem.cod_produtos_cesta)
LEFT JOIN produtos_kits
ON (produtos.sku = produtos_kits.sku)
LEFT JOIN produtos as produtos2
ON (produtos_kits.sku_r = produtos2.sku)
WHERE
shopper_id = '" + mscsShopperId + #"'
GROUP BY
produtos_cesta.cod_produtos_cesta,
tab_contagem.cont,
produtos_cesta.sku,
produtos_kits.sku_r,
produtos.cod_produtos_kits_tipo,
produtos2.estoque,
produtos.controla_estoque,
produtos.estoque,
produtos.status,
produtos.nome_pequeno,
produtos_cesta.unidades,
produtos_cesta.quantidade,
produtos_kits.quantidade
ORDER BY
produtos_cesta.sku,
produtos_cesta.unidades DESC
As most above have lined up the return column names, I find lining up tables names and conditions helps readability a lot.
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2 INNER JOIN
table3 ON table2.column1 = table3.column1
)
And for when join conditions get long.
SELECT
Column1,
Column2
FROM
Table1 JOIN
Table2 ON
Table1.Column3 = Table2.Column4 JOIN
Table3 ON
Table2.Column1 = Table3.Column1 and
Table2.ColumnX = #x and
Table3.ColumnY = #y
WHERE
Condition1=xxx and
Condition2=yyy and
(
Condition3=aaa or
Condition4=bbb
)
Of course, this comes down to personal preference. And if in a team setting, it's something that should be agreed upon among the members for consistency's sake. But this would be my preference:
SELECT column1, column2
FROM table1
WHERE column3 IN(SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON
table2.column1 = table3.column1
)
I would format like this:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1)
or like this:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON table2.column1 = table3.column1)
Well, of course it depends on the query.
For simple queries, a highly formal indentation scheme is just more trouble than it's worth and can actually make the code less readable, not more. But as complexity grows you need to start being more careful with how you structure the statement, to make sure it will be readable again later.
I've just put it through my SQL prettifier and it came out like this....
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
http://extras.sqlservercentral.com/prettifier/prettifier.aspx
.....But I haven't worked out a way of getting colours into StackOverflow.
Yeah, this is pretty subjective...But here's my 2 cents:
SELECT
Column1,
Column2
FROM Table1
WHERE
Column3 IN (
SELECT Column4
FROM Table2
JOIN Table3 ON
Table2.Column1 = Table3.Column1
)
But, really, I'd probably rewrite it without the IN:
SELECT
Column1,
Column2
FROM Table1
JOIN Table2 ON
Table1.Column3 = Table2.Column4
JOIN Table3 ON
Table2.Column1 = Table3.Column1
Basically, my rules are:
Capitalize Keywords
Columns go on individual lines, but SELECT modifiers (SELECT TOP 100, SELECT DISTINCT, etc.) or single columns (SELECT 1, SELECT Id, SELECT *, etc.) go on same line
Join conditions indented underneath JOIN clause
Use JOIN for INNER JOIN (since it's the common one), and fully specify others (LEFT OUTER JOIN, FULL OUTER JOIN, etc.)
Open parens on same line, close paren on separate line. If you have an alias, the alias goes with close paren.
This is my normal preference:
SELECT column1
,column2
FROM table1
WHERE column3 IN (
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
I don't know if there's a standard but I like to do it this way;
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
because I can read and analyze the SQL better.
SELECT
Column1,
Column2
FROM
Table1
WHERE
Column3 IN
(
SELECT TOP (1)
Column4
FROM
Table2
INNER JOIN
Table3
ON
Table2.Column1 = Table3.Column1
)
What I usually do is,
print("SELECT column1, column2
FROM table1
WHERE column3 IN (SELECT TOP(1) column4
FROM table2 INNER JOIN
table3 ON table2.column1 = table3.column1)");
This is a matter of taste.
This is my preference.
SELECT
column1
,column2
FROM
table1
WHERE column3 IN (
SELECT TOP(1) column4
FROM
table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
That's how we would do it here:
select
COLUMN1,
COLUMN2,
case when COLUMN5 = 'X'
and
COLUMN6 = 'Y'
then 'one'
when COLUMN5 in (
'AAA',
'BBB'
)
then 'two'
else 'three'
end as COLUMN7
from
TABLE1
where
COLUMN2 in (
select top(1)
COLUMN4
from
TABLE2
inner join
TABLE3
on
TABLE2.COLUMN1 = TABLE3.COLUMN1
and
TABLE2.COLUMN2
between
TABLE3.COLUMN2
and
TABLE3.COLUMN3
)
Our idea is: keep sql keywords in lower case and put all changing (and therefore "more interesting") things like table or column names in upper case.
The code might look a bit "blown up" here, but it increases readability if you have complex queries with longer names (incl. schema etc.) much longer than in this example.
And: indent all objects according to their "level".
Related
Looking for some help with BigQuery.
I can't seem to use CTEs in UPDATE statements, i.e:
with ctename as
(select
column1,
column2,
column3,
from blah)
update table2
set table2.column2 = ctename.column2
from table2
inner join ctename
on ctename.column1 = table2.column1
I can't find any reason as to why this shouldn't work in BigQuery. Any help/advice would be greatly appreciated.
Looks like below is equivalent of what you are trying to achieve, while technically preserving your cte's query (that obviously can be much much more complex than just select * from the blah)
update table2
set column2 = ctename.column2
from (
select column1, column2, column3
from blah
) ctename
where ctename.column1 = table2.column1
Note: as it is implicitly comes from your question and from other answer(s) - it is expected that that there is 1:1 matches by column1 - otherwise you will get error
I don't think BigQuery supports CTEs in updates. You can write this logic as:
update table2
set table2.column2 = (select blah.column2 from blah where blah.column1 = table2.column1)
where exists (select blah.column2 from blah where blah.column1 = table2.column1);
You can try with SELECT query and JOIN in CTE as follows:
with cte as
(select
blah.column1,
blah.column2,
blah.column3,
table2.column2 as t2col2
from blah
inner join table2
on blah.column1 = table2.column1)
update cte
set t2col2= column2;
After carefully reading a lot of topics about comparing tables and using the minus function I'm posting this.
I've got my comparison between two tables running.
Select Column1,Column2.. from table 1
minus Column1,Column2.. from table 2
union all
Column1,Column2.. from table 2
Select Column1,Column2.. from table 1
order by column1
Now this gives me a list of duplicate or single values that are different in each table. This is fine. However I do not have an indicator telling me in which table the (faulty) rows are.
I tried adding a temporary column giving it an A and B field. This results in a full export of the table because this obviously gets taken in with the minus function.
Is there a way that I can tag the rows telling me what table they are in without adding a permanent column in the table,because this is not an option.
Help is much appreciated!
I would phrase this as a union of left joins:
SELECT t1.col1, t1.col2, 'table1' AS label
FROM table1 t1
LEFT JOIN table2 t2
ON t1.col1 = t2.col1 AND t1.col2 = t2.col2
WHERE t2.col1 IS NULL
UNION ALL
SELECT t2.col1, t2.col2, 'table2'
FROM table2 t2
LEFT JOIN table1 t1
ON t1.col1 = t2.col1 AND t1.col2 = t2.col2
WHERE t1.col1 IS NULL
The label column is computed during the UNION and serves to label the origin table for each record (i.e. set of values) which are unique to that particular table. Note that you can extend what I have given above by adding the necessary number of columns to fill both tables.
This is a general solution which should work across most RDBMS, and doesn't rely on any set difference operators.
Demo here:
SQLFiddle
The example query you provided isn't syntactically correct and has errors when running. But, based on the description of what you tried, I think I understand what you're trying to accomplish.
You were on the right track with adding a temporary column that provides an indicator of which table is the source of the row. The value of the temporary column should be the same for the queries before the UNION ALL and a different value for the queries after.
Here's an updated version of your example query. You can try it out at SqlFiddle
(
SELECT 'FromTable1', COLUMN1, COLUMN2, COLUMN3 FROM TABLE1
EXCEPT
SELECT 'FromTable1', COLUMN1, COLUMN2, COLUMN3 FROM TABLE2
)
UNION ALL
(
SELECT 'FromTable2', COLUMN1, COLUMN2, COLUMN3 FROM TABLE2
EXCEPT
SELECT 'FromTable2', COLUMN1, COLUMN2, COLUMN3 FROM TABLE1
)
I'm trying to combine these 2 statements, have tried alot of searches online but I am just flumoxed and tried all sorts of combinations that don't seem to work (in Toad for Oracle).
Help !
statement 1 (to be done once statement 2 done)
select *
from climate_trends.CT05_baseline_values
inner join climate_trends.CT03_grid_boxes
on climate_trends.CT05_baseline_values.location_id
=
climate_trends.CT03_grid_boxes.grid_box
statement 2
select *
from climate_trends.CT05_baseline_values
where averaging_period_id in ('Spr','Sum','Aut','Win')
and climate_variable_id in('MeanTemp')
and location_type_id = 'Box'
and baseline_period = '1981-2010';
I've now added the real values if this makes better sense? Trying to get one single table where CT03 holds the spatial reference I need to make the join to...
I think you are looking for a UNION SELECT
select * from table5
inner join table3
on table5 = table3
union
select * from table5
where column1 in ('A','B','C','D')
and column2 in('Variable1')
and column3 = 'Variable2'
and column4 = Variable3';
select *
from table3
join (select * from table5
where column1 in ('A','B','C','D')
and column2 in('Variable1')
and column3 = 'Variable2'
and column4 = Variable3') tabke5 on table5 = table3
Seems that with statement 2 you are trying to filter baselines which you got as result of statement 1.
If it's right then just add filtering conditions from statement 2 to statement 1 :
select *
from climate_trends.CT05_baseline_values as baselines
inner join climate_trends.CT03_grid_boxes as boxes
on baselines.location_id = boxes.grid_box
where
baselines.averaging_period_id in ('Spr','Sum','Aut','Win')
and
baselines.climate_variable_id in('MeanTemp')
and
baselines.location_type_id = 'Box'
and
baselines.baseline_period = '1981-2010'
I wasn't able to come up with the right keywords to search for the answer for this, so apologies if it was answered already.
Consider the following SQL view:
CREATE VIEW View1 AS
SELECT Column1
,Column2
,(SELECT SUM(Column3) FROM Table2 WHERE Table2.ID = Table1.ID) -- Subquery
FROM Table1
If I run the following query, will the subquery be executed or does SQL Server optimise the query?
SELECT Column1 FROM View1
I'm looking at this from a performance point of view, say, if the view has quite a few subqueries (aggregations can take a long time if the inner select refers to a large table).
I'm using SQL Server 2008 R2, but I'm interested to know if the answer differs for 2012 or maybe MySQL.
Thanks.
As has been said, this varies depending on your DBMS (version and provider), to know for sure check the execution plan. This shows for SQL-Server 2008 the subquery is not executed:
As you can see in the top plan where Column3 is not selected the plan is simply selecting from table1, in the bottom plan that in includes Column3, table2 is queried.
In SQL-Server 2008 R2 it is not executed.
In SQL-Server 2012 it is not executed;
In MySQL it is executed, and both queries generate the same plan:
To elaborate further, it will also depend on your exact query, as well as your DBMS. For example:
CREATE VIEW View2
AS
SELECT t.ID, t.Column1, t.Column2, t2.Column3
FROM Table1 t
LEFT JOIN
( SELECT ID, Column3 = SUM(Column3)
FROM Table2
GROUP BY ID
) t2
ON t2.ID = t.ID
GO
SELECT Column1, Column2
FROM View2;
SELECT Column1, Column2, Column3
FROM View2;
In this case you get similar results to the correlated subquery, The plan shows only a select from table1 if column3 is not selected, because it is a LEFT JOIN the optimiser knows that the subquery t2 has no bearing on the select from table1, and no columns are used so it does not bother with it. If you changed the LEFT JOIN to an INNER JOIN though, e.g.
CREATE VIEW View3
AS
SELECT t.ID, t.Column1, t.Column2, t2.Column3
FROM Table1 t
INNER JOIN
( SELECT ID, Column3 = SUM(Column3)
FROM Table2
GROUP BY ID
) t2
ON t2.ID = t.ID
GO
SELECT Column1, Column2
FROM View3;
SELECT Column1, Column2, Column3
FROM View3;
The query plan for these two queries shows that because the aggregate column is not used in the second query, the optimiser essentially changes the view to this:
SELECT t.ID, t.Column1, t.Column2
FROM Table1 t
INNER JOIN
( SELECT DISTINCT ID
FROM Table2
) t2
ON t2.ID = t.ID;
As seen by the appearance of the Distinct Sort on table2 and the removal of the Stream Aggregate.
So to summarise, it depends.
The view is just a definition, like a temporary table in a query.
First the query behind the view will be executed and then your selection on the view. So yes the subquery will be executed. If you don't want this you should create a new view without the subquery.
I currently run this query:
UPDATE table1
SET column1 = table2.columnA
FROM table2
WHERE column2 = table2.columnA
AND column3 = table2.columnC
Yes there is a duplicate column, sorry.
When I cross reference column2 with table2.columnA there is a chance to get NULL because column2 DOES NOT contain / where as table2.columnA may contain /
I don't want to change the data in table2.columnA
It is my understanding that I can run this query to REPLACE the characters.
SELECT REPLACE ([table2.columnA],'/','-')
FROM table2
It is necessary that this does not make a permanent change to table2 so I want to make sure that I am getting this right or to see if there is a better way.
Now I want to combine the two queries but am unsure how.
UPDATE table1
SET column1 = table2.columnA
FROM table2
WHERE column2 = (SELECT REPLACE([table2.columnA],'/','-')table2.columnA)
FROM table2
AND column3 = table2.columnC
Thanks for the help!
Something like
UPDATE table1
SET column1 = table2.columnA
FROM table1
inner join table2
on table1.column2 = REPLACE([table2.columnA],'/','-')
and table1.column3 = table2.columnC