从sql中的两个单独的表中加入逻辑

时间:2012-12-27 19:42:30

标签: sql database oracle

我们在查询后返回了cardID个列表,而cardID个属于两个表StudentPersonnel。那么我如何将cardIDStudentPersonnel加入,以便我可以返回一个显示StudentPersonnel名称的表格。到cardID' s?

人员表:

PERSONNELID NUMBER(9,0) 
PERSONNELNAME   VARCHAR2(20)    
PERSONNELSURNAME    VARCHAR2(20)    
PERSONNELJOB    VARCHAR2(40)    
PERSONNELCARDID NUMBER(4,0) 

学生表:

STUDENTID   NUMBER(9,0) 
STUDENTNAME VARCHAR2(20)    
STUDENTSURNAME  VARCHAR2(20)    
STUDENTDEPT VARCHAR2(40)    
STUDENTFACULTY  VARCHAR2(20)    
STUDENTCARDID   NUMBER(4,0) 

CardID

   CARDID   NUMBER(4,0) 
   USERTYPE VARCHAR2(20)    
   CHARGE   NUMBER(3,2) 
   CREDIT   NUMBER(4,2) 

PaymentDevice 表:

    ORDERNO NUMBER  
    PAYDEVIP    NUMBER(8,0) 
    PAYDEVDATE  DATE    No  
    PAYDEVTIME  VARCHAR2(8) 
    CHARGEDCARDID   NUMBER(9,0) 
    MEALTYPE       VARCHAR2(10)

我试图在2012年12月27日返回在自助餐厅吃的前10个人的姓名和姓氏

SELECT C.CARDID
FROM CARD C, PAYMENTDEVICE P
WHERE P.ORDERNO
BETWEEN (SELECT MIN(ORDERNO)
FROM PAYMENTDEVICE
WHERE PAYDEVDATE='27/12/2012') AND (SELECT MIN(ORDERNO)
FROM PAYMENTDEVICE
WHERE PAYDEVDATE='27/12/2012')+10    AND C.CARDID=P.CHARGEDCARDID;

我们的orderNo每天都不会重置,但会不断增加,所以我们找到当天的最小orderNo并在此值中加上10,以找到当天之间那天吃的前10个人号。

那么从这个查询返回什么:

  CARDID
  1005
  1000
  1002
  1003
  1009
  2000
  2001
  1007
  2002
  1004
  1006

那些cardId(以1开头)中的一些是studentCardId,其中一些(以2开头)是PersonnelCardId。那么如何相应地匹配和写入名称呢?

2 个答案:

答案 0 :(得分:1)

SELECT *
FROM Personel p INNER JOIN Student s 
ON p.PersonnelCardId = s.StudentCardId 
INNER JOIN ReturnedQuery rq
ON rq.CardId = p.PersonnelCardId

更新

    SELECT p.PersonnelName, rq.CardId
    FROM Personel p INNER JOIN ReturnedQuery rq
    ON rq.CardId = p.PersonnelCardId 

    UNION

    SELECT s.StudentName, rq.Cardid
    FROM Student s INNER JOIN ReturnedQuery rq 
    ON s.StudentCardId = rq.Cardid 

答案 1 :(得分:1)

您的原始查询实际上非常脆弱。我会像这样重写它(并添加了所需的连接):

WITH First_Daily_Purchase as (SELECT chargedCardId,
                                     MIN(payDevTime) as payDevTime, 
                                     MIN(orderNo) as orderNo
                              FROM PaymentDevice
                              WHERE payDevDate >= 
                                              TO_DATE('2012-12-27', 'YYYY-MM-DD')
                                    AND payDevDate <
                                              TO_DATE('2012-12-28', 'YYYY-MM-DD')
                              GROUP BY chargedCardId),
     First_10_Daily_Purchasers as (SELECT chargedCardId
                                   FROM (SELECT chargedCardId, 
                                                RANK() OVER(ORDER BY payDevTime,
                                                                 orderNo) as rank
                                         FROM First_Daily_Purchase) a
                                   WHERE a.rank < 11)
SELECT a.chargedCardId, b.personnelName, b.personnelSurname
FROM First_10_Daily_Purchasers a
JOIN Personnel b
ON b.personnelCardId = a.chargedCardId
UNION ALL
SELECT a.chargedCardId, b.studentName, b.studentSurname
FROM First_10_Daily_Purchasers a
JOIN Student b
ON b.studentCardId = a.chargedCardId

(有一个working SQL Fiddle - 通常防弹,这花了我一段时间。)
这应该会让你前10个人购买(而不是第一个 11 购买,这是你实际获得的)。这当然假设payDevTime实际上是以可排序的格式存储的(如果不是你的问题比这个查询不能正常工作那么大。)

也就是说,您的架构设计存在许多令人不安的问题。