简体   繁体   中英

#1222 - The used SELECT statements have a different number of columns

Why am i getting a #1222 - The used SELECT statements have a different number of columns ? i am trying to load wall posts from this users friends and his self.

SELECT u.id AS pid, b2.id AS id, b2.message AS message, b2.date AS date FROM 
(
    (
        SELECT b.id AS id, b.pid AS pid, b.message AS message, b.date AS date FROM 
        wall_posts AS b 
        JOIN Friends AS f ON f.id = b.pid 
        WHERE f.buddy_id = '1' AND f.status = 'b'
        ORDER BY date DESC
        LIMIT 0, 10
    )
    UNION
    (
        SELECT * FROM
        wall_posts
        WHERE pid = '1'
        ORDER BY date DESC
        LIMIT 0, 10
    )
    ORDER BY date DESC
    LIMIT 0, 10
) AS b2 
JOIN Users AS u
ON b2.pid = u.id
WHERE u.banned='0' AND u.email_activated='1'
ORDER BY date DESC
LIMIT 0, 10

The wall_posts table structure looks like id date privacy pid uid message

The Friends table structure looks like Fid id buddy_id invite_up_date status

pid stands for profile id. I am not really sure whats going on.

The first statement in the UNION returns four columns:

SELECT b.id AS id, 
       b.pid AS pid, 
       b.message AS message, 
       b.date AS date 
  FROM wall_posts AS b 

The second one returns six , because the * expands to include all the columns from WALL_POSTS :

SELECT b.id, 
       b.date, 
       b.privacy,
       b.pid. 
       b.uid message
  FROM wall_posts AS b 

The UNION and UNION ALL operators require that:

  1. The same number of columns exist in all the statements that make up the UNION'd query
  2. The data types have to match at each position/column

Use:

FROM ((SELECT b.id AS id, 
             b.pid AS pid, 
             b.message AS message, 
             b.date AS date 
        FROM wall_posts AS b 
        JOIN Friends AS f ON f.id = b.pid 
       WHERE f.buddy_id = '1' AND f.status = 'b'
    ORDER BY date DESC
       LIMIT 0, 10)
      UNION
      (SELECT id,
              pid,
              message,
              date
         FROM wall_posts
        WHERE pid = '1'
     ORDER BY date DESC
        LIMIT 0, 10))

You're taking the UNION of a 4-column relation ( id , pid , message , and date ) with a 6-column relation ( * = the 6 columns of wall_posts ). SQL doesn't let you do that.

(
        SELECT b.id AS id, b.pid AS pid, b.message AS message, b.date AS date FROM 
        wall_posts AS b 
        JOIN Friends AS f ON f.id = b.pid 
        WHERE f.buddy_id = '1' AND f.status = 'b'
        ORDER BY date DESC
        LIMIT 0, 10
    )
    UNION
    (
        SELECT id, pid  , message , date  
        FROM
        wall_posts
        WHERE pid = '1'
        ORDER BY date DESC
        LIMIT 0, 10
    )

You were selecting 4 in the first query and 6 in the second, so match them up.

Beside from the answer given by @omg-ponies; I just want to add that this error also occur in variable assignment. In my case I used an insert; associated with that insert was a trigger. I mistakenly assign different number of fields to different number of variables. Below is my case details.

INSERT INTO tab1 (event, eventTypeID, fromDate, toDate, remarks)
    -> SELECT event, eventTypeID, 
    -> fromDate, toDate, remarks FROM rrp group by trainingCode;
ERROR 1222 (21000): The used SELECT statements have a different number of columns

So you see I got this error by issuing an insert statement instead of union statement. My case difference were

  1. I issued a bulk insert sql

    ie insert into tab1 (field, ...) as select field, ... from tab2

  2. tab2 had an on insert trigger; this trigger basically decline duplicates

It turns out that I had an error in the trigger. I fetch record based on new input data and assigned them in incorrect number of variables.

DELIMITER @@
DROP TRIGGER trgInsertTrigger @@
CREATE TRIGGER trgInsertTrigger
BEFORE INSERT ON training
FOR EACH ROW
BEGIN
SET @recs = 0;
SET @trgID = 0;
SET @trgDescID = 0;
SET @trgDesc = '';
SET @district = '';
SET @msg = '';

SELECT COUNT(*), t.trainingID, td.trgDescID, td.trgDescName, t.trgDistrictID
    INTO @recs, @trgID, @trgDescID, @proj, @trgDesc, @district
    from training as t
    left join trainingDistrict as tdist on t.trainingID = tdist.trainingID
    left join trgDesc as td on t.trgDescID = td.trgDescID
    WHERE
    t.trgDescID = NEW.trgDescID
    AND t.venue = NEW.venue
    AND t.fromDate = NEW.fromDate 
    AND t.toDate = NEW.toDate 
    AND t.gender = NEW.gender
    AND t.totalParticipants = NEW.totalParticipants
    AND t.districtIDs = NEW.districtIDs;

IF @recs > 0 THEN
    SET @msg = CONCAT('Error: Duplicate Training: previous ID ', CAST(@trgID AS CHAR CHARACTER SET utf8) COLLATE utf8_bin);
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @msg;
END IF;
END @@ 

DELIMITER ; 

As you can see i am fetching 5 fields but assigning them in 6 var. (My fault totally I forgot to delete the variable after editing.

You are using MySQL Union.

UNION is used to combine the result from multiple SELECT statements into a single result set.

The column names from the first SELECT statement are used as the column names for the results returned. Selected columns listed in corresponding positions of each SELECT statement should have the same data type. (For example, the first column selected by the first statement should have the same type as the first column selected by the other statements.)

Reference: MySQL Union

Your first select statement has 4 columns and second statement has 6 as you said wall_post has 6 column. You should have same number of column and also in same order in both statement. otherwise it shows error or wrong data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM