functional_deps.out 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. -- from http://www.depesz.com/index.php/2010/04/19/getting-unique-elements/
  2. CREATE TEMP TABLE articles (
  3. id int CONSTRAINT articles_pkey PRIMARY KEY,
  4. keywords text,
  5. title text UNIQUE NOT NULL,
  6. body text UNIQUE,
  7. created date
  8. );
  9. CREATE TEMP TABLE articles_in_category (
  10. article_id int,
  11. category_id int,
  12. changed date,
  13. PRIMARY KEY (article_id, category_id)
  14. );
  15. -- test functional dependencies based on primary keys/unique constraints
  16. -- base tables
  17. -- group by primary key (OK)
  18. SELECT id, keywords, title, body, created
  19. FROM articles
  20. GROUP BY id;
  21. id | keywords | title | body | created
  22. ----+----------+-------+------+---------
  23. (0 rows)
  24. -- group by unique not null (fail/todo)
  25. SELECT id, keywords, title, body, created
  26. FROM articles
  27. GROUP BY title;
  28. ERROR: column "articles.id" must appear in the GROUP BY clause or be used in an aggregate function
  29. LINE 1: SELECT id, keywords, title, body, created
  30. ^
  31. -- group by unique nullable (fail)
  32. SELECT id, keywords, title, body, created
  33. FROM articles
  34. GROUP BY body;
  35. ERROR: column "articles.id" must appear in the GROUP BY clause or be used in an aggregate function
  36. LINE 1: SELECT id, keywords, title, body, created
  37. ^
  38. -- group by something else (fail)
  39. SELECT id, keywords, title, body, created
  40. FROM articles
  41. GROUP BY keywords;
  42. ERROR: column "articles.id" must appear in the GROUP BY clause or be used in an aggregate function
  43. LINE 1: SELECT id, keywords, title, body, created
  44. ^
  45. -- multiple tables
  46. -- group by primary key (OK)
  47. SELECT a.id, a.keywords, a.title, a.body, a.created
  48. FROM articles AS a, articles_in_category AS aic
  49. WHERE a.id = aic.article_id AND aic.category_id in (14,62,70,53,138)
  50. GROUP BY a.id;
  51. id | keywords | title | body | created
  52. ----+----------+-------+------+---------
  53. (0 rows)
  54. -- group by something else (fail)
  55. SELECT a.id, a.keywords, a.title, a.body, a.created
  56. FROM articles AS a, articles_in_category AS aic
  57. WHERE a.id = aic.article_id AND aic.category_id in (14,62,70,53,138)
  58. GROUP BY aic.article_id, aic.category_id;
  59. ERROR: column "a.id" must appear in the GROUP BY clause or be used in an aggregate function
  60. LINE 1: SELECT a.id, a.keywords, a.title, a.body, a.created
  61. ^
  62. -- JOIN syntax
  63. -- group by left table's primary key (OK)
  64. SELECT a.id, a.keywords, a.title, a.body, a.created
  65. FROM articles AS a JOIN articles_in_category AS aic ON a.id = aic.article_id
  66. WHERE aic.category_id in (14,62,70,53,138)
  67. GROUP BY a.id;
  68. id | keywords | title | body | created
  69. ----+----------+-------+------+---------
  70. (0 rows)
  71. -- group by something else (fail)
  72. SELECT a.id, a.keywords, a.title, a.body, a.created
  73. FROM articles AS a JOIN articles_in_category AS aic ON a.id = aic.article_id
  74. WHERE aic.category_id in (14,62,70,53,138)
  75. GROUP BY aic.article_id, aic.category_id;
  76. ERROR: column "a.id" must appear in the GROUP BY clause or be used in an aggregate function
  77. LINE 1: SELECT a.id, a.keywords, a.title, a.body, a.created
  78. ^
  79. -- group by right table's (composite) primary key (OK)
  80. SELECT aic.changed
  81. FROM articles AS a JOIN articles_in_category AS aic ON a.id = aic.article_id
  82. WHERE aic.category_id in (14,62,70,53,138)
  83. GROUP BY aic.category_id, aic.article_id;
  84. changed
  85. ---------
  86. (0 rows)
  87. -- group by right table's partial primary key (fail)
  88. SELECT aic.changed
  89. FROM articles AS a JOIN articles_in_category AS aic ON a.id = aic.article_id
  90. WHERE aic.category_id in (14,62,70,53,138)
  91. GROUP BY aic.article_id;
  92. ERROR: column "aic.changed" must appear in the GROUP BY clause or be used in an aggregate function
  93. LINE 1: SELECT aic.changed
  94. ^
  95. -- example from documentation
  96. CREATE TEMP TABLE products (product_id int, name text, price numeric);
  97. CREATE TEMP TABLE sales (product_id int, units int);
  98. -- OK
  99. SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
  100. FROM products p LEFT JOIN sales s USING (product_id)
  101. GROUP BY product_id, p.name, p.price;
  102. product_id | name | sales
  103. ------------+------+-------
  104. (0 rows)
  105. -- fail
  106. SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
  107. FROM products p LEFT JOIN sales s USING (product_id)
  108. GROUP BY product_id;
  109. ERROR: column "p.name" must appear in the GROUP BY clause or be used in an aggregate function
  110. LINE 1: SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
  111. ^
  112. ALTER TABLE products ADD PRIMARY KEY (product_id);
  113. -- OK now
  114. SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
  115. FROM products p LEFT JOIN sales s USING (product_id)
  116. GROUP BY product_id;
  117. product_id | name | sales
  118. ------------+------+-------
  119. (0 rows)
  120. -- Drupal example, http://drupal.org/node/555530
  121. CREATE TEMP TABLE node (
  122. nid SERIAL,
  123. vid integer NOT NULL default '0',
  124. type varchar(32) NOT NULL default '',
  125. title varchar(128) NOT NULL default '',
  126. uid integer NOT NULL default '0',
  127. status integer NOT NULL default '1',
  128. created integer NOT NULL default '0',
  129. -- snip
  130. PRIMARY KEY (nid, vid)
  131. );
  132. CREATE TEMP TABLE users (
  133. uid integer NOT NULL default '0',
  134. name varchar(60) NOT NULL default '',
  135. pass varchar(32) NOT NULL default '',
  136. -- snip
  137. PRIMARY KEY (uid),
  138. UNIQUE (name)
  139. );
  140. -- OK
  141. SELECT u.uid, u.name FROM node n
  142. INNER JOIN users u ON u.uid = n.uid
  143. WHERE n.type = 'blog' AND n.status = 1
  144. GROUP BY u.uid, u.name;
  145. uid | name
  146. -----+------
  147. (0 rows)
  148. -- OK
  149. SELECT u.uid, u.name FROM node n
  150. INNER JOIN users u ON u.uid = n.uid
  151. WHERE n.type = 'blog' AND n.status = 1
  152. GROUP BY u.uid;
  153. uid | name
  154. -----+------
  155. (0 rows)
  156. -- Check views and dependencies
  157. -- fail
  158. CREATE TEMP VIEW fdv1 AS
  159. SELECT id, keywords, title, body, created
  160. FROM articles
  161. GROUP BY body;
  162. ERROR: column "articles.id" must appear in the GROUP BY clause or be used in an aggregate function
  163. LINE 2: SELECT id, keywords, title, body, created
  164. ^
  165. -- OK
  166. CREATE TEMP VIEW fdv1 AS
  167. SELECT id, keywords, title, body, created
  168. FROM articles
  169. GROUP BY id;
  170. -- fail
  171. ALTER TABLE articles DROP CONSTRAINT articles_pkey RESTRICT;
  172. ERROR: cannot drop constraint articles_pkey on table articles because other objects depend on it
  173. DETAIL: view fdv1 depends on constraint articles_pkey on table articles
  174. HINT: Use DROP ... CASCADE to drop the dependent objects too.
  175. DROP VIEW fdv1;
  176. -- multiple dependencies
  177. CREATE TEMP VIEW fdv2 AS
  178. SELECT a.id, a.keywords, a.title, aic.category_id, aic.changed
  179. FROM articles AS a JOIN articles_in_category AS aic ON a.id = aic.article_id
  180. WHERE aic.category_id in (14,62,70,53,138)
  181. GROUP BY a.id, aic.category_id, aic.article_id;
  182. ALTER TABLE articles DROP CONSTRAINT articles_pkey RESTRICT; -- fail
  183. ERROR: cannot drop constraint articles_pkey on table articles because other objects depend on it
  184. DETAIL: view fdv2 depends on constraint articles_pkey on table articles
  185. HINT: Use DROP ... CASCADE to drop the dependent objects too.
  186. ALTER TABLE articles_in_category DROP CONSTRAINT articles_in_category_pkey RESTRICT; --fail
  187. ERROR: cannot drop constraint articles_in_category_pkey on table articles_in_category because other objects depend on it
  188. DETAIL: view fdv2 depends on constraint articles_in_category_pkey on table articles_in_category
  189. HINT: Use DROP ... CASCADE to drop the dependent objects too.
  190. DROP VIEW fdv2;
  191. -- nested queries
  192. CREATE TEMP VIEW fdv3 AS
  193. SELECT id, keywords, title, body, created
  194. FROM articles
  195. GROUP BY id
  196. UNION
  197. SELECT id, keywords, title, body, created
  198. FROM articles
  199. GROUP BY id;
  200. ALTER TABLE articles DROP CONSTRAINT articles_pkey RESTRICT; -- fail
  201. ERROR: cannot drop constraint articles_pkey on table articles because other objects depend on it
  202. DETAIL: view fdv3 depends on constraint articles_pkey on table articles
  203. HINT: Use DROP ... CASCADE to drop the dependent objects too.
  204. DROP VIEW fdv3;
  205. CREATE TEMP VIEW fdv4 AS
  206. SELECT * FROM articles WHERE title IN (SELECT title FROM articles GROUP BY id);
  207. ALTER TABLE articles DROP CONSTRAINT articles_pkey RESTRICT; -- fail
  208. ERROR: cannot drop constraint articles_pkey on table articles because other objects depend on it
  209. DETAIL: view fdv4 depends on constraint articles_pkey on table articles
  210. HINT: Use DROP ... CASCADE to drop the dependent objects too.
  211. DROP VIEW fdv4;
  212. -- prepared query plans: this results in failure on reuse
  213. PREPARE foo AS
  214. SELECT id, keywords, title, body, created
  215. FROM articles
  216. GROUP BY id;
  217. EXECUTE foo;
  218. id | keywords | title | body | created
  219. ----+----------+-------+------+---------
  220. (0 rows)
  221. ALTER TABLE articles DROP CONSTRAINT articles_pkey RESTRICT;
  222. EXECUTE foo; -- fail
  223. ERROR: column "articles.keywords" must appear in the GROUP BY clause or be used in an aggregate function