數據庫聯表查詢及重復記錄字段合並


  最近ssm項目做數據庫連表查詢時,需要查詢l_doctor_order_daily_statistic 表的所有數據,同時在 l_account_bank_card表中如果a.doctorid=c.account_id時,則查詢該賬號的銀行卡號,如果不存在則只顯示l_doctor_order_daily_statistic 表中的信息,因為銀行卡可能有很多張,所以需要合並BANK_CARD_NO字段。
  查詢語句如下:

<select id="findList" resultType="DoctorOrderDailyStatistic">        
        SELECT
        <include refid="doctorOrderDailyStatisticColumns" />
        ,GROUP_CONCAT(c.BANK_CARD_NO SEPARATOR ",") AS "bankCardNo"
        FROM l_doctor_order_daily_statistic a left join l_account_bank_card c on a.doctorid=c.account_id
        <include refid="doctorOrderDailyStatisticJoins" />
        <where>
            1=1 and c.STATUS=1
            <if test="doctorid != null and doctorid != ''">
            AND a.doctorid=#{doctorid}
            </if>
            <if test="statisticdate != null and statisticdate != ''">
            AND a.statisticdate=#{statisticdate}
            </if>
            <if test="beginDate != null and beginDate != ''">
            <![CDATA[     AND a.statisticDate >= #{beginDate}  ]]>
            </if>
            <if test="endDate != null and endDate != ''">
            <![CDATA[    AND a.statisticDate <= #{endDate} ]]>
            </if>
        </where>
         GROUP BY a.doctorid
        <choose>
            <when test="page !=null and page.orderBy != null and page.orderBy != ''">
                ORDER BY ${page.orderBy}
            </when>
            <otherwise>
            </otherwise>
        </choose>
    </select>

  下面講一下連表查詢和合並字段

一、連表查詢

  連接查詢包括合並、內連接、外連接和交叉連接,如果涉及多表查詢,了解這些連接的特點很重要。
 
   1、Union
  UNION 操作符用於合並兩個或多個 SELECT 語句的結果集。
  UNION 運算符通過組合其他兩個結果表(例如 TABLE1 和 TABLE2)並消去表中任何重復行而派生出一個結果表。
  當 ALL 隨 UNION 一起使用時(即 UNION ALL),不消除重復行。
  兩種情況下,派生表的每一行不是來自 TABLE1 就是來自 TABLE2。
   注意:使用UNION時,兩張表查詢的結果有相同數量的列、列類型相似
  學生表信息(Students):
 
      
ID   Name Age City MajorID

101

Tom 20 BeiJing 10
102 Lucy 18 ShangHai 11
  
 
 
 
 
  教師表信息(Teachers):
ID Name
101 Mrs Lee
102 Lucy
 
 
  1)基本UNION查詢,查詢學校教師、學生的總的信息表,包括ID和姓名
SELECT ID,Name FROM Students
UNION
SELECT ID,Name FROM Teachers
  查詢結果:
ID Name
101 Mrs Lee
101 Tom
102 Lucy

 

  2)帶條件的UNION查詢,也可以查詢同一張表,查詢年齡為18,23歲的學生信息
SELECT ID,Name FROM Student WHERE Age=18
UNION
SELECT ID,Name FROM Student WHERE Age=23

 

  3)查詢教師學生全部姓名
   因為UNION只會選擇不同的值,如果學生中和教師中有重名的情況,這就需要UNION ALL
  
SELECT Name FROM Students
UNION ALL
SELECT Name FROM Teachers
  查詢結果:
ID Name
101 Tom
102 Lucy
101 Mrs Lee
102 Lucy

 

   2、INNER JOIN(內連接)
  INNER JOIN(內連接),也成為自然連接
  作用:根據兩個或多個表中的列之間的關系,從這些表中查詢數據。
   注意: 內連接是從結果中刪除其他被連接表中沒有匹配行的所有行,所以內連接可能會丟失信息。
  重點:內連接,只查匹配行。
  語法:(INNER可省略)
SELECT fieldlist
FROM table1 [INNER] join table2
ON table1.column=table2.column
  學生表信息(Students):
ID Name Age City MajorID
101 Tom 20 BeiJing 10
102 Lucy 18 ShangHai 11
 
  專業信息表(Majors): 
ID Name
10 English
12 Computer

  

   實例:查詢學生信息,包括ID,姓名、專業名稱
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students INNER JOIN Majors
ON Students.MajorID = Majors.ID
   查詢結果:
ID Name MajorName
101 Tom English
 
  根據結果可以清晰看到,學生Lucy的信息丟失了,只顯示匹配的行。
  但是,inner join也會產生重復數據。如果將Majors表的主鍵約束去掉,可以插入重復的ID,如:
DELETE FROM Majors
INSERT INTO Majors(ID,Name) VALUES(10,'English')
INSERT INTO Majors(ID,Name) VALUES(10,'Computer')
  繼續執行上面的關聯語句,結果為:
ID Name MajorName
101 Tom English
101 Tom Computer
 
  如果是LEFT JOIN也會有重復記錄,其結果為:
ID Name MajorName
101 Tom English
101 Tom Computer
102 Lucy NULL
 
   3、外連接
  與內連接相比,即使沒有匹配行,也會返回一個表的全集。
  外連接分為三種:左外連接,右外連接,全外連接。對應SQL:LEFT/RIGHT/FULL OUTER JOIN。通常我們省略outer 這個關鍵字。寫成:LEFT/RIGHT/FULL JOIN。
   重點:至少有一方保留全集,沒有匹配行用NULL代替。
 
   1)LEFT OUTER JOIN,簡稱LEFT JOIN,左外連接(左連接)
   結果集保留左表的所有行,但只包含第二個表與第一表匹配的行。第二個表相應的空行被放入NULL值。
  依然沿用內連接的例子
  (1)使用左連接查詢學生的信息,其中包括學生ID,學生姓名和專業名稱。
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students LEFT JOIN Majors
ON Students.MajorID = Majors.ID
  結果:
ID Name MajorName
101 Tom English
102 Lucy NULL
 
 
    結論:
  通過結果,我們可以看到左連接包含了第一張表的所有信息,在第二張表中如果沒有匹配項,則用NULL代替
 
   2)RIGHT JOIN(right outer join)右外連接(右連接)
   右外連接保留了第二個表的所有行,但只包含第一個表與第二個表匹配的行。第一個表相應空行被入NULL值。
  右連接與左連接思想類似。只是第二張保留全集,如果第一張表中沒有匹配項,用NULL代替依然沿用內鏈接的例子,只是改為右連接
 
  (1)使用右連接查詢學生的信息,其中包括學生ID,學生姓名和專業名稱。
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students RIGHT JOIN Majors
ON Students.MajorID = Majors.ID
  查詢結果:
ID Name MajorName
101 Tom English
NULL NULL Computer
 
  通過結果可以看到,包含了第二張表Majors的全集,Computer在Students表中沒有匹配項,就用NULL代替。 
 
   3)FULL JOIN (FULL OUTER JOIN,全外連接)
  全外連接,簡稱:全連接。會把兩個表所有的行都顯示在結果表中
  1)使用全連接查詢學生的信息,其中包括學生ID,學生姓名和專業名稱。
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students FULL JOIN Majors
ON Students.MajorID = Majors.ID
  查詢結果: 
ID Name MajorName
101 Tom English
102 Lucy NULL
NULL NULL Computer
 
   包含了兩張表的所有記錄,沒有記錄丟失,沒有匹配的行用NULL代替。
 
   4、CROSS JOIN(交叉連接)
  交叉連接。交叉連接返回左表中的所有行,左表中的每一行與右表中的所有行組合。交叉連接也稱作笛卡爾積。 
  簡單查詢兩張表組合,這是求笛卡兒積,效率最低。
  笛卡兒積:笛卡爾乘積,也叫直積。假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。可以擴展到多個集合的情況。類似的例子有,如果A表示某學校學生的集合,B表示該學校所有課程的集合,則A與B的笛卡爾積表示所有可能的選課情況。
 
 1)交叉連接查詢學生的信息,其中包括學生ID,學生姓名和專業名稱。
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students CROSS JOIN Majors
  查詢結果:
ID Name MajorName
101 Tom English
102 Lucy English
101 Tom Computer
102 Lucy Computer
 
 
  2)查詢多表,其實也是笛卡兒積,與CROSS JOIN等價,以下查詢同上述結果一樣。
  這個可能很常見,但是大家一定要注意了,這樣就查詢了兩張表中所有組合的全集。
  
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students,Majors
  3)加了查詢條件
  注意:在使用CROSS JOIN關鍵字交叉連接表時,因為生成的是兩個表的笛卡爾積,因而 不能使用ON關鍵字,只能在WHERE子句中定義搜索條件。
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students CROSS JOIN Majors WHERE Students.MajorID = Majors.ID
  查詢結果:
ID Name MajorName
101 Tom English
 
  查詢結果與INNER JOIN一樣,但是其效率就慢很多了。
 
二、重復記錄同一字段的合並
  一個字段可能對應多條數據,用mysql實現將多行數據合並成一行數據
  例如:一個活動id(activeId)對應多個模塊名(modelName),按照一般的sql語句:
  
SELECT am.activeId,m.modelName 
 FROM activemodel am 
 JOIN  model m 
 ON am.modelId = m.modelId 
 ORDER BY am.activeId
  查詢結果:
activeId modelname
1 吃飯
1 游泳
3 行車
4 唱歌
4 打球

 

修改過后的sql語句,查詢后如圖:
SELECT am.activeId,GROUP_CONCAT(m.modelName SEPARATOR ',') modelName
 FROM activemodel am 
 JOIN model m 
 ON am.modelId=m.modelId
 WHERE m.valid=1
 GROUP BY am.activeId

  查詢結果:

activeId modelName
1 吃飯,游泳
3 行車
4 唱歌,打球
 
1.GROUP_CONCAT()中的值為你要合並的數據的字段名;
 SEPARATOR 函數是用來分隔這些要合並的數據的;
 ' '中是你要用哪個符號來分隔;
2.必須要用GROUP BY 語句來進行分組管理,不然所有的數據都會被合並成一條記錄

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM