[Wolves] Happy Christmas ...and help me with this mysql query

Chris Ellis chris.ellis.intrbiz at googlemail.com
Fri Dec 28 18:48:26 UTC 2012


Hi Wayne

On 28 December 2012 14:47, Wayne Morris <waynelists at machx.co.uk> wrote:
> On 27/12/2012 18:19, Andy Smith wrote:
> <lots of useful stuff>
>
> Hi,
>  I should clarify that Part1 on Item1 is not the same as Item1 on Part2,
> just the name is the same!
>  So having a separate table for the Parts is a bit pointless.
> Lets try again with houses, I want a list of unique houses at the end.
>
> Each house has a distinct street address, possible same postcode (for two
> houses next door), same town.
> Each house is broken up into Rooms - room1 -> room 14 (big apartment
> blocks).
>
> So all I did was set up one table for all 750 unique rooms, having ID,
> street address (address2) , Room No (address1) postcode as fields (and then
> sub tables for tenants, histories etc).

While you think this is simple, you have run into the reason why it is
bad practise.  When designing a database, your goal should be to *NOT*
duplicate data.  Hence why this should be broken into two tables,
rooms relate to a property.  You are also running into problems around
natural keys and beloved auto-incrementing IDs.

You should break the data into two tables:

(In PostgreSQL SQL)

CREATE TABLE property (
    id serial PRIMARY KEY,
    address TEXT,
    CONSTRAINT property_pk PRIMARY KEY (id)
);

CREATE TABLE room (
    property integer REFERENCES property (id),
    room TEXT,
    CONSTRAINT room_pk PRIMARY KEY (property, room)
)

As an example of why you should do this, what happends then you
realise the street address is incorrect and the record need to be
updated?  You don't actually have a unique ID for a property, this
seems shortsighted and foolish.

>
> So, trying to get a list of each individual house (about 150) rather than
> each room
>
> SELECT DISTINCT (address2 ) FROM property ORDER BY address2 LIMIT 0 , 300
> seems to produce a list of individual houses but
>
> I can't populate the report as if i change it to:
>
> SELECT DISTINCT (address2 ) FROM property as ID, address1, address2, rent
> ORDER BY address2 LIMIT 0 , 300
> it goes balmy with duplicates

I really hope MySQL doesn't actually execute this query, its utter bollox.

>
> select * from property where address2 like '%1%'  would be really simple
> query if I could get rid of the duplicates caused by rooms over 10

To actually query your table structure as is, either omit the ID field
when using SELECT DISTINCT, eg:

SELECT DISTINCT address_1, address_2 FROM properties WHERE address_1
LIKE '%blah%' ORDER BY address_1, address_2;

If your insistent on returning your pointless autoinc ID too, you need
to get more complex:

SELECT q.*, (SELECT p.id FROM properties p WHERE p.address_1 =
q.address_1 AND p.address_2 = q.address_2 LIMIT 1) AS id FROM (
	SELECT DISTINCT address_1, address_2 FROM properties ORDER BY
address_1, address_2
) q
WHERE address_1 LIKE '%1%'
ORDER BY address_1, address_2;

I'm a PostgreSQL DBA, so prefer PostgreSQL, which has a rather handy
form of DISTINCT, which as far as I'm aware MySQL doesn't support, in
PostgreSQL I can do:

CREATE TABLE properties (
	id SERIAL,
	address_1 TEXT,
	address_2 TEXT,
	room TEXT,
	CONSTRAINT properies_pk PRIMARY KEY (id)
);

INSERT INTO properties (address_1, address_2, room) VALUES ('Street1',
'Street1.2', 'Room1');
INSERT INTO properties (address_1, address_2, room) VALUES ('Street1',
'Street1.2', 'Room2');
INSERT INTO properties (address_1, address_2, room) VALUES ('Street1',
'Street1.2', 'Room3');

INSERT INTO properties (address_1, address_2, room) VALUES ('Street2',
'Street2.2', 'Room1');
INSERT INTO properties (address_1, address_2, room) VALUES ('Street2',
'Street2.2', 'Room2');
INSERT INTO properties (address_1, address_2, room) VALUES ('Street2',
'Street2.2', 'Room3');

INSERT INTO properties (address_1, address_2, room) VALUES ('Street3',
'Street3.2', 'Room1');
INSERT INTO properties (address_1, address_2, room) VALUES ('Street3',
'Street3.2', 'Room2');
INSERT INTO properties (address_1, address_2, room) VALUES ('Street3',
'Street3.2', 'Room3');

INSERT INTO properties (address_1, address_2, room) VALUES
('Street10', 'Street10.2', 'Room1');
INSERT INTO properties (address_1, address_2, room) VALUES
('Street10', 'Street10.2', 'Room2');
INSERT INTO properties (address_1, address_2, room) VALUES
('Street10', 'Street10.2', 'Room3');


SELECT DISTINCT ON (address_1, address_2) id, address_1, address_2
FROM properties
WHERE address_1 like '%1%'
ORDER BY address_1, address_2;

In summary, my advice would be to revise your table structure so it is
sane.  Databases are very good at joining data between tables, I
suggest you look at:
http://en.wikipedia.org/wiki/Database_normalization

Regards,
Chris E.



More information about the Wolves mailing list