【问题标题】:Will it be possible to join table with itself是否可以与自身连接表
【发布时间】:2015-09-26 15:27:13
【问题描述】:

这个查询的结果是否能够在不相乘的情况下加入。

Select StudID, StudName, StudYear from tbl_students where StudYear='Third Year';
Select StudID, StudName, StudYear from tbl_students where StudYear='Second Year';
Select StudID, StudName, StudYear from tbl_students where StudYear='First Year';

或者这些查询的“结果”是否有可能与 9 列连接,指的是第三年的前 3 列,第二年的后 3 列和第一年的后 3 列。 谢谢你的好意回答。

结果我想到的是这样的

学生证 |学生姓名 |学生年 ----------------------------------------- 1 | foo1 | 1 ----------------------------------------- 2 | foo2 | 1 ----------------------------------------- 3 | foo3 | 2 ----------------------------------------- 4 | foo4 | 2 ----------------------------------------- 5 | foo5 | 2 ----------------------------------------- 6 | foo6 | 3 ----------------------------------------- 学生 ID-1 |学生姓名-1 | StudentYear-1 |学生ID-2 |学生姓名-2 |学生二年级 |学生ID-3 |学生姓名-3 | StudentYear-3 -------------------------------------------------- -------------------------------------------------- ------------------------------------------------ 1 | foo1 | 1 | 3 | foo3 | 2 |6 | foo6 | 3 -------------------------------------------------- -------------------------------------------------- ------------------------------------------------ 2 | foo2 | 1 | 4 | foo4 | 2 | | | -------------------------------------------------- -------------------------------------------------- ------------------------------------------------ | | | 5 | foo5 | 2 | | | -------------------------------------------------- -------------------------------------------------- ------------------------------------------------

【问题讨论】:

  • 你想要什么结果?
  • 每一行代表什么?它不能代表一个学生。由于不能,因此不清楚是什么将给定行中的一年级学生与二年级和三年级学生绑定在一起。您是否尝试使用它来生成特定布局的表格(每年一组列,每年都有独立的行)?如果是这样,我建议在应用程序逻辑中这样做,而不是在您的查询中。
  • 我建议将此问题移至dba.stackexchange.com。和this 可能会帮助你
  • 请更新您的问题并告诉我们您是如何得出所显示结果的。由于原始表中的行与结果表中的行之间的关系似乎是随机的。谢谢。

标签: mysql sql


【解决方案1】:

好的,将我的答案更改为使用子查询并将每个子查询视为具有自己别名列的表。这不会产生您想要的确切结果,这将在其他 6 个未填充的列中产生空值。话虽如此,我相信这与您将在查询中做您想做的事情差不多。

SELECT StudentFirst.*, StudentSecond.*, StudentThird.*
FROM (((tbl_students ts 
left join (SELECT StudID AS StudIDFirst, StudName AS StudNameFirst, StudYear AS StudYearFirst FROM tbl_students WHERE StudYear = 'First Year') AS StudentFirst on (ts.StudID = StudentFirst.StudIDFirst))
left join (SELECT StudID AS StudIDSecond, StudName AS StudNameSecond, StudYear AS StudYearSecond FROM tbl_students WHERE StudYear = 'Second Year') AS StudentSecond on (ts.StudID = StudentSecond.StudIDSecond))
left join (SELECT StudID AS StudIDThird, StudName AS StudNameThird, StudYear AS StudYearThird FROM tbl_students WHERE StudYear ='Third Year') AS StudentThird on (ts.StudID = StudentThird.StudIDThird))

这是查询的结果

我会说我不推荐这种方法。 MySQL 在处理子查询方面已经做得更好了,但是 5.5 之前的任何东西都会有可怕的性能,一旦你达到一定的数据水平,即使 5.5 也不会很好。同样使用你的 mysql 语句来格式化结果也不是一个好主意。如果您需要以某种方式查看结果,我会检索记录集,然后将它们以该格式放在应用程序的前端。我希望这会有所帮助。

【讨论】:

  • 类似的东西,但我希望是水平的,而不是垂直的。
  • 抱歉,横向不是严格的要求。这可以通过子查询来完成。如果您仍然有答案,我会在回家时修复我的答案。
  • 感谢您的努力帮助!这正是我想要发生的事情。但是,如果知道在另一列上产生未填充的空值,那么很难在第一行上获得值。我得出的结论是,我将为每个实例进行单独的查询。很好的帮助!
【解决方案2】:

要达到你的要求,你必须有一些 id 类型的东西加入,所以使用行号,否则你将一对多对多结果

在 SQL Server 中工作。所以在MYSQL中试一试。

CREATE TABLE #STUDENT(ID INT, NAME VARCHAR(10), STUDENT_YEAR INT);
INSERT INTO #STUDENT VALUES(1,'FOO1',1);
INSERT INTO #STUDENT VALUES(2,'FOO2',1);
INSERT INTO #STUDENT VALUES(3,'FOO3',2);
INSERT INTO #STUDENT VALUES(4,'FOO4',2);
INSERT INTO #STUDENT VALUES(5,'FOO5',2);
INSERT INTO #STUDENT VALUES(6,'FOO6',3);


SELECT * FROM (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY S1.ID ASC) RN,
        S1.ID AS [ID_1], S1.NAME AS [NAME_1],S1.STUDENT_YEAR AS [YEAR_1]  
    FROM #STUDENT S1
    where s1.STUDENT_YEAR=1
) T1    
FULL JOIN (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY S2.ID ASC) RN,
        S2.ID AS [ID_2], S2.NAME AS [NAME_2],S2.STUDENT_YEAR AS [YEAR_2]  
    FROM #STUDENT S2
    where s2.STUDENT_YEAR=2
) T2 ON T1.RN = T2.RN
FULL JOIN (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY S3.ID ASC) RN,
        S3.ID AS [ID_3], S3.NAME AS [NAME_3],S3.STUDENT_YEAR AS [YEAR_3]  
    FROM #STUDENT S3
    where s3.STUDENT_YEAR=3
) T3 ON T1.RN = T3.RN

注意#Student表示它是一个临时表。

【讨论】:

  • 感谢您提出有效的查询。不过,OP 确实指定了 MySQL 标记。
  • 我在我的sql中没有找到full joinrow_number所以只是认为有人可以理解逻辑并可以在mysql中创建它。
  • 它在 MySQL 中不可用。您必须使用两个外部联接的联合来模拟完全联接。行号可以用变量模拟,在整个查询过程中正确初始化和管理。这实际上是一种痛苦。
  • 这在 Oracle 中是可能的,而不是在 MySql 中。
【解决方案3】:

是的,您可以将这些查询合并为

SELECT * FROM
  (Select StudentID, StudentName, StudentYear as Third_StudYear
     from Students
     where StudentYear=3) y3
  CROSS JOIN (Select StudentID, StudentName, StudentYear as Second_StudYear
                from Students
                where StudentYear=2) y2
  CROSS JOIN (Select StudentID, StudentName, StudentYear as First_StudYear
                from Students
                where StudentYear=1) y1

如果那是你真正想做的。

祝你好运。

【讨论】:

  • 该查询可能不会返回任何内容。
  • 现在您已经添加了所需的结果,我可以看到您的意图,但是由于我看不到您打算如何将事物连接在一起,因此我已将其更改为使用 CROSS JOIN,这消除了了解连接关系的需要。 SQLFiddle here。祝你好运。
  • @BobJarvis:您对预期结果的看法是正确的。但是,重复行以匹配编号最高的列。行数。
  • @ZeroSerum - 希望这对 OP 来说是一个有益的练习。
  • 交叉连接不会这样做,它只会将 y3 的结果与 y2 的结果相乘,例如如果 y3 有 3 行而 y2 有 2 行,则 y3 交叉连接 y2 将返回 6 行,y2 的每行从 y3 返回 2 行,并且将其与 y1 交叉连接将进一步增加结果。我建议您避免使用交叉连接,除非您在 WHERE 语句中进行了正确连接,但这会导致内连接、左连接或右连接...
猜你喜欢
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多