DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Enterprise AI Trend Report: Gain insights on ethical AI, MLOps, generative AI, large language models, and much more.

2024 Cloud survey: Share your insights on microservices, containers, K8s, CI/CD, and DevOps (+ enter a $750 raffle!) for our Trend Reports.

PostgreSQL: Learn about the open-source RDBMS' advanced capabilities, core components, common commands and functions, and general DBA tasks.

AI Automation Essentials. Check out the latest Refcard on all things AI automation, including model training, data security, and more.

Related

  • SQL Data Storytelling: A Comprehensive Guide
  • Accelerating Insights With Couchbase Columnar
  • Why SQL Isn’t the Right Fit for Graph Databases
  • SQL Data Manipulation Language (DML) Operations: Insert, Update, Delete

Trending

  • Harnessing the Power of Observability in Kubernetes With OpenTelemetry
  • The Power of Generative AI: How It Is Revolutionizing Business Process Automation
  • The Future of Kubernetes: Potential Improvements Through Generative AI
  • Deploying Heroku Apps To Staging and Production Environments With GitLab CI/CD
  1. DZone
  2. Coding
  3. Languages
  4. Simple SQL Statements Only Exist in Coursebooks and Training Courses

Simple SQL Statements Only Exist in Coursebooks and Training Courses

Except for the simplest scenarios, the degree of SQL code complexity increases sharply, even if the task complexity only rises slightly.

By 
Judy Liu user avatar
Judy Liu
·
Jan. 17, 24 · Opinion
Like (3)
Save
Tweet
Share
2.6K Views

Join the DZone community and get the full member experience.

Join For Free

The sample SQL statements in coursebooks are usually simple and easy to understand. They even read like English sentences, giving the impression that SQL is rather simple and easy to learn.

Actually, such a SQL statement consisting of only a few lines of code can only be found in coursebooks and training courses. In real-world businesses, the amount of SQL code is measured by KB instead of the number of lines. One SQL statement having several hundred lines of code and N layers of nested subqueries often reaches 3KB to 5KB in size. Such SQL statements are not easy to learn at all but rather a nightmare even to professional programmers.

The KB-level size itself isn’t a big problem. A long SQL statement is inevitable if the computing goal is truly complicated. The Python or Java counterpart could be even longer. Yet, unlike statements written in other languages, a long SQL statement is not only long but difficult to write and understand. Moreover, the difficulty isn’t proportional to the degree of task complexity. Except for the simplest scenarios, the degree of SQL code complexity increases sharply, even if the task complexity only rises slightly. Programmers need to have very strong abilities in order to accomplish the coding, and those computing scenarios often appear in programming interviews.

Why Does SQL Generate So Long and Difficult Statements?

We mentioned one reason before. The SQL syntax is like English grammar, but the programming language isn’t a procedural type. It puts too many actions in one statement, and this increases the difficulty of working out a computing logic out of thin air.

However, we find that the code is still difficult to understand when the computing task becomes slightly complicated, even after SQL adds the CTE syntax that enables procedural programming.

This is because SQL lacks many expressive abilities. As a result, programmers can only write code in a roundabout way rather than according to the natural way of thinking. 

Let’s look at a simple scenario.

T is a simplified sales performance table. It has three fields: sales (seller), product, and amount (sales amount). We want to find sales whose amounts of both ACs and TVs rank in the top 10. 

The task is simple, and we can design the computing process in a natural way:

  1. Sort records of the table by AC’s amount and get the top 10
  2. Sort records of the table by TV’s amount and get the top 10
  3. Perform intersection on the two result sets to get what we want

 We can write the SQL code with CTE syntax in the following way:

SQL
 
with A as (select top 10 sales from T where product='AC' order by amount desc), B as (select top10 sales from T where product='TV' order by amount desc)
select * from A intersect B


The statement is not very short but is logically clear.

Now, we make the task a little more complicated: find the sales whose amounts of all products rank in the top 10. According to the logic in the previous task, we can code the computing process as follows:

  1.  List all products
  2.  Find sales whose amounts rank in the top 10 for each product and save them separately
  3. Get the intersection of the top 10 sets

Unfortunately, the CTE syntax only supports expressing a definite number of intermediate results. For this task, we do not know the total number of products in advance. That is, the number of WITH clauses is indefinite. So, we are unable to code the current logic with CTE.

Well, let’s switch to a different logic:

  1. Group records of the table by product, sort each group and get the top 10 in each group
  2. Get the intersection of these top 10 sets

To achieve this, we need to save the grouping result obtained in step 1. The intermediate result is a table, where there is a field for storing the top 10 sales in the corresponding group members. This means that its values are sets. SQL lacks the set data type and still cannot code the logic.

Let’s try another solution. Group records by product and find the frequency of each seller at the top of all groups; if the number of appearances is equal to the number of products, the sales are at the top 10 in terms of amount for all products. 

SQL
 
select sales from ( select sales from ( select sales, rank() over (partition by product order by amount desc ) ranking    from T ) where ranking <=10 )
group by sales having count(*)=(select count(distinct product) from T)


Now, we are finally able to write down the code with the help of window functions. But the logic is too roundabout; how many can work it out and put it down on paper?

SQL cannot describe the first two simple logics; we can only adopt the third, more roundabout one. The reason behind this is one of SQL’s major shortcomings: incomplete set-lization.

SQL has the concept of sets, but it does not offer sets as a basic data type. It does not allow field values to be sets and, except for tables, it does not provide any other set data type. As a result, both the logic and the code for implementing the set computations are very roundabout.

In the above code, we use the keyword top. In fact, there isn’t such a keyword in the relational algebra. It isn’t the standard SQL syntax.

But how should we find the top 10 sales without using the keyword top?

The general logic is like this: get the number of members where the amounts are greater than the current one, take it as the ranking, and get members whose rankings are not greater than 10.

SQL
 
select sales from ( select A.sales sales, A.product product, (select count(*)+1 from T where A.product=product and A.amount<=amount) ranking from T A )where product='AC' and ranking<=10


Note that the subquery cannot be written stepwise using the CTE syntax because it uses information in the main query as a parameter.

We can also use join to write the query so that we can handle the computation step by step using the CTE syntax:

SQL
 
select sales from ( select A.sales sales, A.product product, count(*)+1 ranking from T A, T B where A.sales=B.sales and A.product=B.product and A.amount<=B.amount
group by A.sales,A.product ) where product='AC' and ranking<=10


No matter how we implement the query, the logic is always too circuitous. Even a professional programmer needs to think for a while only to get the top10 job done.

This is due to SQL’s other major shortcoming: lack of support for orderliness. SQL inherits the mathematics’ unordered sets. It is rather difficult to take care of computations related to the order – we all know how common they are (link ratio calculation, YOY calculation, getting top 20%, getting rankings, to name a few).

The SQL2003 standard offered some order-related computing ability. This alleviates the difficulty for SQL in coping with order-based computations to some extent. Here is the SQL code to get to the top 10: 

SQL
 
select sales from ( select sales, rank() over (partition by product order by amount desc ) ranking
from T )
where ranking <=10


The subquery is still there.

SQL’s unordered sets base hasn’t been fundamentally changed by window functions. Many order-based computations are still left difficult to tackle, such as counting the longest consecutively rising dates for a certain stock, which we often use as an example scenario:

SQL
 
select max(ContinuousDays) from (    select count(*) ContinuousDays from (        select sum(UpDownTag) over (order by TradeDate) NoRisingDays from (            select TradeDate,case when Price>lag(price) over ( order by TradeDate)then 0 else 1 end UpDownTag from Stock ))    group by NoRisingDays )


The natural way of thinking is this: sort records by date and perform count – add 1 when the price rises and reset the number as 0 when the price drops – and get the largest count. However, the logic cannot be expressed in SQL. With the language, we can only write the query as nested.

The computing task was a real recruitment exam problem, but only 20% of applicants were able to work it out.

SQL’s shortcomings are clear even in such a simple example. The language has more weaknesses, which we won’t discuss in this article.

In a word, SQL cannot express logic according to the natural way of thinking. It usually takes a roundabout route and produces lengthy and difficult-to-understand statements.

Real-world computing tasks are more complicated than these examples. There are various difficulties – big and small – during the process of handling the computations. A roundabout way here and a few more lines there, and it is not strange that a SQL statement for a little complicated task finally has hundreds of lines of multilayer nested code and that two months later, even the authors themselves cannot understand the code.

Indeed, SQL isn’t simple at all.

What can we do about difficult to write SQL statements? Use esProc SPL!

esProc SPL is open-source software written in Java. Download esProc SPL HERE.

SPL adds discreteness on the base of SQL’s existing set-lization and achieves complete set-lization and the ability to exploit data order. We can write code for the second example according to the natural way of thinking in SPL: 

Find records of sales whose amounts for all products rank in top10, group them by product, get top10 members in each group, and then perform intersection:

SQL
 
T.group(product).(~.top(10;-amount)).isect()


SPL supports the use of a set of sets. The “getting top” computation is treated as an ordinary aggregation. Based on these concepts, it is easy to implement natural logics.

To count the longest consecutively rising dates for stock, SPL just writes the code in the natural way of thinking:

SQL
 
cnt=0
Stock.sort(TradeDate).max(cnt=if(Price>Price[-1],cnt+1,0))


SPL boasts powerful order-based computing ability. It is effortless to implement the same logic expressed in the above SQL statement:

SQL
 
Stock.sort(TradeDate).group@i(Price<Price[-1]).max(~.len())


sql Query language

Published at DZone with permission of Judy Liu. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • SQL Data Storytelling: A Comprehensive Guide
  • Accelerating Insights With Couchbase Columnar
  • Why SQL Isn’t the Right Fit for Graph Databases
  • SQL Data Manipulation Language (DML) Operations: Insert, Update, Delete

Partner Resources


Comments

ABOUT US

  • About DZone
  • Send feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: