dimanche 13 mai 2018

Why does RANDOM() in a SQLite CTE JOIN behave differently to other RDBMSs?

Joined RANDOM() -values in a Common Table Expression (CTE) aren't behaving as expected in SQLite.

SQL:

WITH
  tbl1(n) AS (SELECT 1 UNION ALL SELECT 2),
  tbl2(n, r) AS (SELECT n, RANDOM() FROM tbl1)
SELECT * FROM tbl2 t1 CROSS JOIN tbl2 t2;

Sample results:

n   r                       n   r
1   7058971975145008000     1   8874103142384122000
1   1383551786055205600     2   8456124381892735000
2   2646187515714600000     1   7558324128446983000
2   -1529979429149869800    2   7003770339419606000

The random numbers in each column are all different. But a CROSS JOIN repeats rows so I expected 2 pairs of the same number in each column. The same thing in SQL Server 2014 returns the random numbers all the same!

n   r                   n   r
1   0.699059921278562   1   0.850848909375491
1   0.699059921278562   2   0.850848909375491
2   0.699059921278562   1   0.850848909375491
2   0.699059921278562   2   0.850848909375491

UPDATE: I now understand. SQL Server assigns a random seed to the RAND() function. When used in a SELECT it is only seeded once rather than for each row. Changing the tbl2 CTE to (SELECT n, RANDOM(n) FROM tbl1) fixes this.

And then the same in PostgreSQL and Oracle 11g. This time the results were as expected:

n   r                   n   r
1   0.117551110684872   1   0.117551110684872
1   0.117551110684872   2   0.221985165029764
2   0.221985165029764   1   0.117551110684872
2   0.221985165029764   2   0.221985165029764

Questions

  1. Can this behaviour in SQLite be explained? Is it a bug?
  2. Is there a way for a Table B in a CTE (which is based on Table A in the same CTE) to have an additional column of randomly generated numbers, which will remain fixed when used in a JOIN?



Aucun commentaire:

Enregistrer un commentaire