There's a far easier way to do what you want - I was thinking about this last night - see my second fiddle here.
You can do something like the following (all the code below is available on the fiddle here):
CREATE TABLE test
(
t_id INTEGER NOT NULL PRIMARY KEY,
status_to VARCHAR (50)
);
Then populate it:
INSERT INTO test VALUES
(7, NULL), (8, 'Test_val_1'), (9, 'Test_val_2'),
(3, 'Publish'), (4, 'Action'), (5, 'Sold'), (6, 'Let'), (10, 'Draft'), (11, 'Unpublish'),
(12, 'Publish'), (13, 'Action'), (14, 'Sold'), (15, 'Let'), (26, 'Draft'), (16, 'Unpublish'),
(17, 'Publish'), (18, 'Action'), (19, 'Sold'), (20, 'Let'), (27, 'Draft'), (21, 'Unpublish'),
(22, 'Publish'), (23, 'Action'), (24, 'Sold'), (25, 'Let'), (1, 'Draft'), (2, 'Unpublish'),
(29, NULL), (30, NULL), (35, 'Test_val_1'), (31, 'Test_val_2'),
(45, 'Single_1'), (46, 'Single_2');
Note that I have added 2 singleton values (Single_1
and Single_2
) to examine how one would, for example, count the DISTINCT
values which had greater than 1 record in your table... it's much more difficult with "classic" SQL - with window functions, it's quite easy.
The new "simple" query is:
SELECT
COUNT(DISTINCT(status_to)) AS "Unique count"
FROM
test;
(New) result:
Unique count
10
Notice the extreme difference in the results of EXPLAIN ANALYZE
at the bottom of the fiddle for this new query and my old one!
This query demonstrates how you can easily pick out those DISINCT
values of status_to
that have more than one record:
SELECT COUNT(rn) OVER (PARTITION BY rn) AS "Unique count"
FROM
(
SELECT
t_id, status_to,
ROW_NUMBER() OVER (PARTITION BY status_to ORDER BY status_to) AS rn
FROM test
WHERE status_to IS NOT NULL
ORDER BY status_to, t_id
) AS tab
WHERE rn > 1
GROUP BY status_to
ORDER BY status_to
LIMIT 1;
Result:
Unique count
8
8 = 10 (total) minus the 2 singletons!
I also included this SQL - which lets you easily count (manually) the number of UNIQUE
entries.
SELECT status_to, MAX(rn)
FROM
(
SELECT
t_id, status_to,
ROW_NUMBER() OVER (PARTITION BY status_to ORDER BY status_to) AS rn
FROM test
WHERE status_to IS NOT NULL
ORDER BY status_to, t_id
) AS tab
WHERE rn > 1 <<==== ****
GROUP BY status_to
ORDER BY status_to;
Result:
status_to MAX(rn)
Action 4
Draft 4
Let 4
Publish 4
Sold 4
Test_val_1 2
Test_val_2 2
Unpublish 4
8 rows <<---- note 8 rows!
I've left a few more snippets in the second fiddle - if you really want to learn about SQL, I would invite you to look at both the old and the new and also to try running the code using PostgreSQL - it's interesting!
Finally, if you wish to dynamically construct a row (as per your original question) with all of your DISTINCT
values and their COUNT()
s, then you could possibly use some form of RECURSIVE CTE
- but that's for another question!