Illegal mix of collations?

Hey all,

I am working through the sitepoint book Simply SQL, nearly finished the section of the book on SQL but I got this error 'Illegal mix of collations for operation 'UNION'' when running the following query from the books:
SELECT
  *
FROM (
  SELECT
    customers.name    AS customer
  , carts.id          AS cart
  , items.name        AS item
  , cartitems.qty
  , items.price
  , cartitems.qty
        * items.price AS total
  FROM
    customers
      INNER JOIN carts
        ON carts.customer_id = customers.id
      INNER JOIN cartitems
        ON cartitems.cart_id = carts.id
      INNER JOIN items
        ON items.id = cartitems.item_id

  UNION ALL

  SELECT
    customers.name                  AS customer
  , NULL                            AS cart
  , CAST(COUNT(items.name) AS CHAR) AS item
  , NULL                            AS qty
  , NULL                            AS price
  , SUM(cartitems.qty
        * items.price)              AS total
  FROM
    customers
      INNER JOIN carts
        ON carts.customer_id = customers.id
      INNER JOIN cartitems
        ON cartitems.cart_id = carts.id
      INNER JOIN items
        ON items.id = cartitems.item_id
  GROUP BY
    customers.name
  ) AS dt
ORDER BY
  customer
, cart
, item
;

Could someone kindly tell me what this error means, and why im getting it? thanks! :slight_smile:

Not 100% sure how mySQL works with collations, but based on what I know from other RDBMS, the problem is the group by changes the collation and UNIONs require matching collations to put the two sets of records together.

You can specify a collation, and if you need a list of the valid choices, here you [URL=“http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html”]are, or if you want some opinions on the best choice to use, [URL=“http://stackoverflow.com/questions/367711/what-is-the-best-collation-to-use-for-mysql-with-php”]this SIZE=1[/SIZE] thread is an interesting read.

i have to admit, i never ran across any sort of collation problems when i was doing the testing for the book

i simply created my tables without ever specifying any collations, so presumably i got the defaults

if you do a SHOW CREATE TABLE for each of the tables, this might uncover something where an individual column was given a different collation from the default

other than that, i have no idea about where your error came from

by the way, that UNION query (with its “interleaving” of total and detail rows) is the trickiest in the whole book, so once you’re past it, you’ll be a qualified SQL master

:cool:

Hello Rudy!

 Thankyou very much for your reply. I have to say, this is an extremely well written book - and I dont say that often! I usually go off tech books after reading a few pages due to being so dry but this wasnt the case.

What exactly is Collation out of interest? It would be good to get this final query running for sure :slight_smile: Also I was wondering if anyone can suggest a good way to consolidate the principles I learnt in this book? I dont have any SQL based projects on the go at present that I can test my new skills on :slight_smile:

Oh by the way, here is the results of the SHOW TABLE :


customers 	CREATE TABLE `customers` (
 `id` int(11) NOT NULL,
 `name` varchar(99) COLLATE utf8_unicode_ci NOT NULL,
 `billaddr` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `shipaddr` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'See billing address.',
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

carts 	CREATE TABLE `carts` (
 `id` int(11) NOT NULL,
 `customer_id` int(11) NOT NULL,
 `cartdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

cartitems 	CREATE TABLE `cartitems` (
 `cart_id` int(11) NOT NULL,
 `item_id` int(11) NOT NULL,
 `qty` smallint(6) NOT NULL DEFAULT '1'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

items 	CREATE TABLE `items` (
 `id` int(11) NOT NULL,
 `name` varchar(21) COLLATE utf8_unicode_ci NOT NULL,
 `type` varchar(7) COLLATE utf8_unicode_ci NOT NULL,
 `price` decimal(5,2) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

this might help…
http://dev.mysql.com/doc/refman/5.5/en/charset-general.html

thanks for the kind words about the book – it took a lot of work to make it seem so simple

as for testing your skills, perhaps you could build a rudimentary CMS? using the tables in the book, but adding additional columns or even tables to flesh it out more towards a real-world app

[QUOTE=r937;5039960]this might help…
http://dev.mysql.com/doc/refman/5.5/en/charset-general.html
Thanks for the info, I will read that document this evening for sure :slight_smile: And yes that sounds like a great idea.

By the way, with regards to the aforementioned error, both of the queries in the UNION work individually but not as part of that ‘mega query’ - any idea why this might be?

not really, no

would you consider re-installing the tables from the book’s code and trying again?

i notice that some of your columns specify a collation and others don’t (whereas the sample code provided mentioned no collations at all)

Yeah I will give that a bash, thanks again Rudy!!

I tried setting COLLATE on the group by clause, but sadly no change :frowning:

Put the collate on both statements to ensure you’re getting the same collation. That should right the ship…at least it did in SQL Server when I ran into this exact issue.

This appears to be the offending column :


, CAST(COUNT(items.name) AS CHAR) COLLATE utf8_unicode_ci AS item

As you can see I added the COLLATE keyword, and the query actually runs now! Only the grouping isnt working as it should :rofl:

then you’ve done something else wrong :rofl:

Yeah, im beyond confused now to be honest! Think im going to give it a rest :slight_smile:

I got it working :D:rofl: heres my query…


SELECT
  *
	FROM (	
		 SELECT
			  customers.name    AS customer
			, carts.id          AS cart
			, items.name        AS item
			, cartitems.qty
			, items.price
			, cartitems.qty
				* items.price AS total
			FROM
			  customers
				INNER JOIN carts
				  ON carts.customer_id = customers.id
				INNER JOIN cartitems
				  ON cartitems.cart_id = carts.id
				INNER JOIN items
				  ON items.id = cartitems.item_id

			UNION ALL

			SELECT
			  customers.name    AS customer
			, NULL              AS cart
			, COUNT(items.name) AS item
			, NULL              AS qty
			, NULL              AS price
			, SUM(cartitems.qty
				 * items.price) AS total
			FROM
			  customers
				INNER JOIN carts
				  ON carts.customer_id = customers.id
				INNER JOIN cartitems
				  ON cartitems.cart_id = carts.id
				INNER JOIN items
				  ON items.id = cartitems.item_id
			GROUP BY
			customers.name
		) AS dt
ORDER BY
  customer
, cart
, item
;

A good nights sleep was all that was needed (my client had me up fixing Javascript bugs all evening). I re-wrote the query from scratch, this time I removed the CHAR cast from the Group Query - im not sure why a cast was being performed, but the query runs without it.

I didnt even have to set the COLLATE key word! I also noticed that some of the data in the tables was slightly different between the book and the download, so I dropped all the tables and started again :slight_smile:

that column (called “item”) in the union query results is supposed to be a character column – see the first SELECT where item.name is assigned the “item” alias

the CAST of the COUNT(), which is numeric, was intended to teach the point that columns in a union must be datatype compatible

I get you Rudy! Oh and thanks again for all your help, Dave Maxwell too… thanks! (: