0

I am trying to count rows like in this table:

Product | Product2 | Value
Coke    | Lemon    |   3
Coke    | Potato   |   4
Coke    | Seven Up |   10
Lemon   | Coke     |   3
Lemon   | Meat     |   4
Pancake | Meat     |   23
Potato  | Coke     |   4
Seven Up| Coke     |   10
Meat    | Lemon    |   4
Meat    | Pancake  |   23

I must count the items but if they change order I still must count just once. So in this case I would have a result: 5. By the way, I already tried "where Product!= Product2" but this is not enough.

Can someone tell me what to do in this case? Thanks,

mu is too short
  • 426,620
  • 70
  • 833
  • 800
Samuel Donadelli
  • 347
  • 1
  • 3
  • 12
  • 1
    Can you please explain more ? 5 of what ? – Houari Feb 02 '14 at 20:50
  • For instance, we count a row : Coke | Lemon | 3 . Then we must not count again Lemon | Coke | 3 , just because Lemon changed places with Coke. So applying this idea, considering this table, the result will be 5. Do you know how can I do it using SQL ? Thanks, – Samuel Donadelli Feb 02 '14 at 20:55
  • You didn't answer Houari's question: 5 what? If you meant you want to count the number of *distinct products*, then (a) there are 6 of them, and (b) why not say that? – j_random_hacker Feb 02 '14 at 21:33
  • 2
    @j_random_hacker: Distinct unordered pairs, i.e. distinct `(product, product1)` pairs where `(a,b)` and `(b,a)` are considered to be the same. – mu is too short Feb 02 '14 at 21:36

2 Answers2

4

Since you only have two columns, you can use greatest and least to ignore the column order:

select greatest(product, product2) as a,
       least(product, product2) as b
from t
order by a, b

will give you:

Lemon    | Coke
Lemon    | Coke
Meat     | Lemon
Meat     | Lemon
Pancake  | Meat
Pancake  | Meat
Potato   | Coke
Potato   | Coke
Seven Up | Coke
Seven Up | Coke

Then toss in a distinct and count:

select count(
  distinct (
    greatest(product, product2),
    least(product, product2)
  )
)
from t

Demo: http://sqlfiddle.com/#!15/32111/6

mu is too short
  • 426,620
  • 70
  • 833
  • 800
2

Based on This array sorting function, we can convert rows to an arrays, sort the array, and than select distinct values:

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(SELECT unnest($1) ORDER BY 1)
$$;

and than:

SELECT count( distinct array_sort(array[product, product2]  ) ) FROM your_table

Hope that helps

Community
  • 1
  • 1
Houari
  • 5,326
  • 3
  • 31
  • 54
  • 2
    This nicely generalizes to more than two product columns where the `greatest`/`least` trick doesn't work: http://sqlfiddle.com/#!15/518b4/1 – mu is too short Feb 02 '14 at 21:44