问题
I have a table that looks like the following which shows the count of types. I need to and have been trying to display data as 1 column and 7 rows instead though... without success.
__________________________________________________________________________ | col types | win2k | winxp | win2k3 | vista | win7 | win8 | win8.1 | -------------------------------------------------------------------------- | count of types | 2365 | 65655 | 422445 | 4822 | 482 | 2331 | 485323 | --------------------------------------------------------------------------
Select
count(case when col1 ~* '5.0.2195' then 1 else null end) as Win2k,
count(case when col1 ~* '5.1.2600' then 1 else null end) as WinXP,
count(case when col1 ~* '5.2.3790' then 1 else null end) as W2k3,
count(case when (col1 ~* '6.0.6000'
or col1 ~* '6.0.6001' or col1 ~* '6.0.6002')
then 1 else null end) as Vista,
count(case when (col1 ~* '6.1.7600'
or col1 ~* '6.1.7601')
then 1 else null end) as Win7,
count(case when col1 ~* '6.2.9200' then 1 else null end) as Win8,
count(case when (col1 ~* '6.3.9200'
or col1 ~* '6.3.9600')
then 1 else null end) as "Win8.1"
From col1
Ideally it would look something like this:
___________________ | types | count | ------------------- | win2k | 2365 | | winxp | 65655 | | win2k3 | 422445 | | vista | 4822 | | win7 | 482 | | win8 | 2331 | | win8.1 | 485323 | -------------------
Notes:
- I am using Postgresql 9.3 with PGADMIN III
- I cannot create any custom functions
- It wouldn't matter if there were more columns to make this work
回答1:
These type of queries are easier to make with an aim of GROUP BY, like this:
Select
case when profile.foo ~* '5.0.2195' then 'Win2k'
when profile.foo ~* '5.1.2600' then 'WinXP'
when profile.foo ~* '5.2.3790' then 'W2k3'
when (profile.foo ~* '6.0.6000'
or profile.foo ~* '6.0.6001'
or profile.foo ~* '6.0.6002')
then 'Vista'
when (profile.foo ~* '6.1.7600'
or profile.foo ~* '6.1.7601')
then 'Win7'
when profile.foo ~* '6.2.9200' then 'Win8'
when (profile.foo ~* '6.3.9200'
or profile.foo ~* '6.3.9600')
then 'Win8.1' ELSE 'Other' END as type,
count(*) as cnt
From profile
GROUP BY 1
As commented below this query will work for mutually exclusive cases, i.e. when profile.foo
contains a value representing one OS per row
回答2:
Instead of using conditional aggregates, just use CASE
to populate the Type
appropriately then group on Type
:
;with cte AS (Select case when profile.foo ~* '5.0.2195' then 'Win2k'
when profile.foo ~* '5.1.2600' then 'WinXP'
when profile.foo ~* '5.2.3790' then 'W2k3'
when profile.foo ~* '6.0.6000' or profile.foo ~* '6.0.6001' or profile.foo ~* '6.0.6002' then 'Vista'
when (profile.foo ~* '6.1.7600' or profile.foo ~* '6.1.7601') then 'Win7'
when profile.foo ~* '6.2.9200' then 'Win8'
when (profile.foo ~* '6.3.9200' or profile.foo ~* '6.3.9600') then 'Win8.1'
end as Type
From profile.foo)
SELECT Type,COUNT(*) AS ct
FROM cte
GROUP BY Type
Not 100% on postgresql syntax, but the logic is compatible.
回答3:
I like to use the Postgres specific parallel unnest()
for this:
SELECT unnest('{win2k,winxp,win2k3,vista,win7,win8,win8.1}'::text[]) AS type
,unnest(ARRAY[
count(some_column ~ '5.0.2195' OR NULL)
,count(some_column ~ '5.1.2600' OR NULL)
.. the rest from your query above ...
]) AS ct
FROM profile.foo
Sequence and number of values in both arrays must match.
Related answers with more details (be sure to read up!):
Parallel unnest() and sort order in PostgreSQL
Is there something like a zip() function in PostgreSQL that combines two arrays?
Alternative counting technique (optional)
count()
only counts non-null values..
(TRUE OR NULL) IS TRUE
(FALSE OR NULL) IS NULL
(NULL OR NULL) IS NULL
Voilá. Only TRUE
is counted. More details in this answer on dba.SE.
Aside: Using ~ instead of ~* in the expressions, since there are no case sensitive letters in these string literals. But I doubt you need a regular expression match at all.
Also, the column names profile.foo
don't make sense, since the only table is named foo
, not profile
来源:https://stackoverflow.com/questions/25797850/sql-query-to-transpose-column-counts-to-row-counts