12

为什么我得到 #1222 - 使用的 SELECT 语句有不同的列数?我正在尝试从该用户的朋友和他自己那里加载墙帖。

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

wall_posts 表结构看起来像id date privacy pid uid message

Friends 表结构看起来像Fid id buddy_id invite_up_date status

pid 代表配置文件 ID。我不太确定发生了什么事。

4

5 回答 5

26

UNION 中的第一条语句返回四列:

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

第二个返回6,因为 * 扩展为包含来自 的所有列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))
于 2010-10-15T22:55:04.107 回答
4

您正在UNION使用 4 列关系(idpidmessagedate)和 6 列关系(*= 的 6 列wall_posts)。SQL 不允许你这样做。

于 2010-10-15T22:55:01.863 回答
3
(
        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.

于 2010-10-15T22:56:52.813 回答
1

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

    i.e. 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.

于 2020-09-21T10:38:38.403 回答
0

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.

于 2019-12-03T07:08:12.980 回答