一、SQL找不一樣位數html
select length(aae135),count(1) from ac01 group by length(aae135) ;數據庫
————————————————————————————————app
二、SQL查詢重複數據ide
有例表:emp函數
emp_no name age 001 Tom 17 002 Sun 14 003 Tom 15 004 Tom 16post
要求:學習
列出全部名字重複的人的記錄url
(1)最直觀的思路:要知道全部名字有重複人資料,首先必須知道哪一個名字重複了:htm
select name from emp group by name having count(*)>1blog
全部名字重複人的記錄是:
select * from emp where name in (select name from emp group by name having count(*)>1)
(2)稍微再聰明一點,就會想到,若是對每一個名字都和原表進行比較,大於2我的名字與這條記錄相同的就是合格的 ,就有
select * from emp where (select count(*) from emp e where e.name=emp.name) >1
--注意一下這個>1,想下若是是 =1,若是是 =2 若是是>2 若是 e 是另一張表 並且是=0那結果 就更好玩了:)
這個過程是 在判斷工號爲001的 人 的時候先取得 001的 名字(emp.name) 而後和原表的名字進行比較 e.name
注意e是emp的一個別名。
再稍微想得多一點,就會想到,若是有另一個名字相同的人工號不與她他相同那麼這條記錄符合要求:
select * from emp where exists (select * from emp e where e.name=emp.name and e.emp_no<>emp.emp_no)
此思路的join寫法:
select emp.* from emp,emp e where emp.name=e.name and emp.emp_no<>e.emp_no/**/ /* 這個語句較規範的 join 寫法是 select emp.* from emp inner join emp e on emp.name=e.name and emp.emp_no<>e.emp_no 但我的比較傾向於前一種寫法,關鍵是更清晰 */ b、有例表:emp name age Tom 16 Sun 14 Tom 16 Tom 16
----------------------------------------------------清除重複---------------------------------------------------- 過濾掉全部多餘的重複記錄 (1)咱們知道distinct、group by 能夠過濾重複,因而就有最直觀的
select distinct * from emp 或 select name,age from emp group by name,age
得到須要的數據,若是可使用臨時表就有解法:
select distinct * into #tmp from emp delete from emp insert into emp select * from #tmp
(2)可是若是不可使用臨時表,那該怎麼辦? 咱們觀察到咱們沒辦法區分數據(物理位置不同,對 SQL Server來講沒有任何區別),思路天然是想辦法把數據區分出來了,既然如今的全部的列都沒辦法區分數據,惟一的辦法就是再加個列讓它區分出來,加什麼列好?最佳選擇是identity列:
alter table emp add chk int identity(1,1)
表示例:
name age chk Tom 16 1 Sun 14 2 Tom 16 3 Tom 16 4
重複記錄能夠表示爲:
select * from emp where (select count(*) from emp e where e.name=emp.name)>1
要刪除的是:
delete from emp where (select count(*) from emp e where e.name=emp.name and e.chk>=emp.chk)>1
再把添加的列刪掉,出現結果。
alter table emp drop column chk
(3)另外一個思路: 視圖
select min(chk) from emp group by name having count(*) >1
得到有重複的記錄chk最小的值,因而能夠
delete from emp where chk not in (select min(chk) from emp group by name)
寫成join的形式也能夠:
(1)有例表:emp
emp_no name age 001 Tom 17 002 Sun 14 003 Tom 15 004 Tom 16
◆要求生成序列號 (1)最簡單的方法,根據b問題的解法:
alter table emp add chk int identity(1,1) 或 select *,identity(int,1,1) chk into #tmp from emp
◆若是須要控制順序怎麼辦?
select top 100000 *,identity(int,1,1) chk into #tmp from emp order by age
(2) 假如不能夠更改表結構,怎麼辦? 若是不能夠惟一區分每條記錄是沒有辦法的,在能夠惟一區分每條記錄的時候,可使用a 中的count的思路解決這個問題
select emp.*,(select count(*) from emp e where e.emp_no<=emp.emp_no) from emp order by (select count(*) from emp e where e.emp_no<=emp.emp_no)
——————————————————————————————————————————————————————————————
group by 有一個原則,就是 select 後面的全部列中,沒有使用聚合函數的列,必須出如今 group by 後面(重要)
例如,有以下數據庫表:
A B 1 abc 1 bcd
1 asdfg
若是有以下查詢語句(該語句是錯誤的,緣由見前面的原則)
select A,B from table group by A
該查詢語句的意圖是想獲得以下結果(固然只是一相情願)
A B abc 1 bcd
asdfg
右邊3條如何變成一條,因此須要用到聚合函數,以下(下面是正確的寫法):
select A,count(B) as 數量 from table group by A 這樣的結果就是 A 數量 1 3
2. Having
where 子句的做用是在對查詢結果進行分組前,將不符合where條件的行去掉,即在分組以前過濾數據,條件中不能包含聚組函數,使用where條件顯示特定的行。
having 子句的做用是篩選知足條件的組,即在分組以後過濾數據,條件中常常包含聚組函數,使用having 條件顯示特定的組,也可使用多個分組標準進行分組。
having 子句被限制子已經在SELECT語句中定義的列和聚合表達式上。一般,你須要經過在HAVING子句中重複聚合函數表達式來引用聚合值,就如你在SELECT語句中作的那樣。例如:
SELECT A COUNT(B) FROM TABLE GROUP BY A HAVING COUNT(B)>2
3.使用compute和compute by 使用compute子句容許同時觀察查詢所獲得各列的數據的細節以及統計各列數據所產生的彙總列 select * from work [查詢所獲得的各列的數據的細節] compute max(基本工資),min(基本工資) [統計以後的結果] 這個例子中沒有使用by關鍵字,返回的結果是最後添加了一行基本工資的最大值和最小值,也可增長by關鍵字. 例:select * from work order by 學歷 compute max(基本工資),min(基本工資) by 學歷 比較:select 學歷,max(基本工資),min(基本工資) from work group by 學歷 說明:1:compute子句必須與order by子句用在一塊兒 2:compute子句能夠返回多種結果集.一種是體現數據細節的數據集,能夠按分類要求進行正確的分類;另外一種在分類的基礎上進行彙總產生結果. 3:而group by子句對每一類數據分類以後只能產生一個結果,不能知道細節
示例學習Northwind數據庫:
非相關查詢:
1:返回每一個美國員工都爲其處理過訂單的全部客戶
--思路:1:Employees表中獲取美國員工總數2:Orders表中查詢美國員工處理的Order,對CustomerID分組後,統計其不一樣的EmployeeID正好等於美國員工總數
Select CustomerID From Orders Where EmployeeID In --獲得美國員工服務 的客戶
(Select EmployeeID From Employees Where Country=N'USA') -- 獲得所有美國員工id
group by CustomerID --按客戶分組
Having Count(Distinct EmployeeID)= --爲其處理訂單的distinct 員工數等於美國總員工數
(Select Count(*) From Employees Where Country=N'USA')--美國員工總數
2:
返回在每個月最後實際訂單日期發生的訂單(每個月最後訂單日期可能不是每個月最後一天)
--思路:子查詢按月分組獲得每個月最近訂單日期
Select OrderID,CustomerID,EmployeeID,OrderDate
From Orders
Where OrderDate In
(Select Max(OrderDate) From Orders Group by Convert(char(6),OrderDate,112))--112表示YYYYMMDD char(6)提取YYYYMM
3.
Select字句在邏輯上是SQL語句最後進行處理的最後一步,因此,如下查詢會發生錯誤:
SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID FROM dbo.Orders) AS D GROUP BY OrderYear ;由於group by是在Select以前進行的,那個時候orderYear這個列並無造成。
若是要查詢成功,能夠像下面進行修改:
SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID FROM dbo.Orders) AS D GROUP BY OrderYear;還有一種很特殊的寫法:
SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts FROM (SELECT YEAR(OrderDate), CustomerID FROM dbo.Orders) AS D(OrderYear, CustomerID) GROUP BY OrderYear;在做者眼裏,他是很是喜歡這種寫法的,由於更清晰,更明確,更便於維護。
在查詢中使用參數定向產生一批結果,這個技巧沒有什麼好說的。
嵌套查詢,在處理邏輯上是從裏向外進行執行的。