Skip to content

Instantly share code, notes, and snippets.

@macdice
Created August 21, 2015 05:37
Show Gist options
  • Save macdice/3731735c58db4949fc62 to your computer and use it in GitHub Desktop.
Save macdice/3731735c58db4949fc62 to your computer and use it in GitHub Desktop.
-- Demo of PostgreSQL 9.5 features for Wellington PostgreSQL User's Group
-- The following is not necessarily in the right order or exactly how I ran it,
-- I mixed it up a bit when presenting!
DROP TABLE IF EXISTS country CASCADE;
DROP TABLE IF EXISTS sales_per_person CASCADE;
DROP TABLE IF EXISTS film CASCADE;
DROP TABLE IF EXISTS work_queue CASCADE;
DROP TABLE IF EXISTS sample;
--- ON CONFLICT
CREATE TABLE country (
id VARCHAR(2) PRIMARY KEY,
name TEXT NOT NULL,
population INTEGER NOT NULL
);
INSERT INTO country (id, name, population)
VALUES ('NZ', 'New Zealand', 4400000),
('AU', 'Australia', 23000000);
SELECT * FROM country;
INSERT INTO country (id, name, population)
VALUES ('NZ', 'New Zealand', 4500000);
UPDATE country
SET population = 64000000
WHERE id = 'GB';
INSERT INTO country (id, name, population)
VALUES ('NZ', 'New Zealand', 4500000)
ON CONFLICT DO NOTHING;
INSERT INTO country (id, name, population)
VALUES ('NZ', 'New Zealand', 4700000),
('FR', 'France', 66000000)
ON CONFLICT ON CONSTRAINT country_pkey
DO UPDATE SET population = excluded.population;
-- GROUPING SETS
--- ROLLUP
CREATE TABLE sales_per_person (
country TEXT REFERENCES country(id),
city TEXT NOT NULL,
salesperson TEXT NOT NULL,
widgets_sold INTEGER NOT NULL,
UNIQUE (country, city, salesperson)
);
INSERT INTO sales_per_person (country, city, salesperson, widgets_sold)
VALUES ('NZ', 'Wellington', 'Alice', 3),
('NZ', 'Wellington', 'Ben', 1),
('NZ', 'Auckland', 'Chris', 4),
('AU', 'Sydney', 'Derek', 1),
('AU', 'Sydney', 'Eric', 5),
('AU', 'Melbourne', 'Fran', 9);
SELECT *
FROM sales_per_person
ORDER BY country, city, salesperson;
SELECT country, SUM(widgets_sold)
FROM sales_per_person
GROUP BY country
ORDER BY country;
SELECT country, city, SUM(widgets_sold)
FROM sales_per_person
GROUP BY country, city
ORDER BY country, city;
SELECT country, city, salesperson, SUM(widgets_sold)
FROM sales_per_person
GROUP BY country, city, salesperson
ORDER BY country, city, salesperson;
WITH results(country, city, salesperson) AS (
SELECT NULL, NULL, NULL, SUM(widgets_sold)
FROM sales_per_person
UNION ALL
SELECT country, NULL, NULL, SUM(widgets_sold)
FROM sales_per_person
GROUP BY country
UNION ALL
SELECT country, city, NULL, SUM(widgets_sold)
FROM sales_per_person
GROUP BY country, city
UNION ALL
SELECT country, city, salesperson, SUM(widgets_sold)
FROM sales_per_person
GROUP BY country, city, salesperson
)
SELECT *
FROM results
ORDER BY country, city, salesperson;
SELECT country, city, salesperson, SUM(widgets_sold)
FROM sales_per_person
GROUP BY ROLLUP (country, city, salesperson)
ORDER BY country, city, salesperson;
--- CUBE
CREATE TABLE film (
name TEXT,
country TEXT,
genre TEXT,
adam_sandler BOOLEAN,
box_office INTEGER
);
INSERT INTO film (name, country, genre, adam_sandler, box_office)
VALUES ('The Return of Foo', 'US', 'horror', true, 42),
('The Return of the Return of Foo', 'US', 'horror', false, 7),
('Java Strikes Back', 'GB', 'comedy', true, 8),
('NullPointerException', 'NZ', 'romance', false, 2),
('Deep Stack Trace 9', 'US', 'adventure', true, 8);
SELECT country, genre, adam_sandler, SUM(box_office)
FROM film
GROUP BY CUBE (country, genre, adam_sandler)
ORDER BY country, genre, adam_sandler;
-- GROUPING SETS
SELECT country, city, salesperson, SUM(widgets_sold)
FROM sales_per_person
GROUP BY GROUPING SETS ((country, city, salesperson),
(country, city),
(country),
())
ORDER BY country, city, salesperson;
SELECT country, genre, adam_sandler, SUM(box_office)
FROM film
GROUP BY GROUPING SETS ((country, genre, adam_sandler),
(country, genre),
(country, adam_sandler),
(genre, adam_sandler),
(country),
(genre),
(adam_sandler),
())
ORDER BY country, genre, adam_sandler;
-- JSON & JSONB
CREATE TABLE document (data JSON);
INSERT INTO document
VALUES ('{ "name": "Alice", "age": 114 }'),
('{ "name": "Bob", "age": 4 }'),
('{ "engine": "v8", "transmission": "manual" }');
INSERT INTO document
VALUES ('{ Ceci n''est pas du JSON');
SELECT * FROM document;
SELECT data, data->>'name' AS name FROM document;
SELECT data FROM document WHERE data->>'transmission' = 'manual';
CREATE TABLE document2 (data JSONB);
INSERT INTO document2
VALUES ('{ "name": "Alice", "age": 114 }'),
('{ "name": "Bob", "age": 4 }'),
('{ "engine": "v8", "transmission": "manual" }');
SELECT * FROM document2;
UPDATE document2
SET data = jsonb_set(data, '{"recipe"}', '{"ingredients": ["icecream", "sauce"]}')
WHERE data->>'transmission' = 'manual';
SELECT * FROM document2;
UPDATE document2
SET data = jsonb_set(data, '{"recipe", "ingredients"}', '["icecream", "sauce", "cherry"]')
WHERE data->>'transmission' = 'manual';
SELECT * FROM document2;
DELETE FROM document2;
INSERT INTO document2
SELECT json_build_object('id', generate_series(1, 1000000), 'name', 'the_borg');
INSERT INTO document2
VALUES ('{"id": -1, "name": "foo", "legs": [ "left", "right" ]}');
SELECT * FROM document2 LIMIT 20;
SELECT * FROM document2 WHERE data @> '{"id": 42}';
SELECT * FROM document2 WHERE data ? 'legs';
SELECT * FROM document2 WHERE data @> '{"legs": ["left"]}';
SELECT * FROM document2 WHERE data @> '{"legs": ["middle"]}';
EXPLAIN ANALYZE SELECT * FROM document2 WHERE data @> '{"id": 42}';
CREATE INDEX my_index ON document2 USING gin(data);
-- BRIN
CREATE TABLE sample (
id SERIAL,
time TIMESTAMPTZ,
data JSON
);
INSERT INTO sample (time, data)
SELECT generate_series('2000-01-01 00:00:00'::TIMESTAMPTZ, now(), '1 minute'::INTERVAL),
'{ "windy": "yes" }';
CREATE INDEX sample_time_btree ON sample(time);
CREATE INDEX sample_time_brin ON sample USING brin(time);
DROP INDEX sample_time_btree;
DROP INDEX sample_time_brin;
ANALYZE sample;
EXPLAIN ANALYZE
SELECT *
FROM sample
WHERE time BETWEEN now() - INTERVAL '2 years' AND now() - INTERVAL '1 week';
-- SKIP LOCKED
CREATE TABLE work_queue (
id INTEGER PRIMARY KEY,
status TEXT,
job TEXT
);
INSERT INTO work_queue
VALUES (1, 'NEW', 'take out the rubbish'),
(2, 'NEW', 'mow the lawn'),
(3, 'NEW', 'stack the firewood');
BEGIN;
SELECT id, job
FROM work_queue
WHERE status = 'NEW'
FOR UPDATE
LIMIT 1;
COMMIT;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment