設(shè)為首頁收藏本站Access中國

Office中國論壇/Access中國論壇

 找回密碼
 注冊

QQ登錄

只需一步,快速開始

返回列表 發(fā)新帖
查看: 2784|回復(fù): 2
打印 上一主題 下一主題

[ADO/DAO] 從MSSQL(SQLSERVER)/MYSQL數(shù)據(jù)庫中隨機(jī)取一條或者多條記錄

[復(fù)制鏈接]

點(diǎn)擊這里給我發(fā)消息

跳轉(zhuǎn)到指定樓層
1#
發(fā)表于 2015-10-24 18:34:08 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
從MSSQL(SQLSERVER)/MYSQL數(shù)據(jù)庫中隨機(jī)取一條或者多條記錄
很多人都知道使用rand()函數(shù)但是怎麼使用可能不是每個(gè)人都知道
摘自樺仔 博文
建立測試表
USE [sss]
GO


CREATE TABLE RANDTEST(ID INT DEFAULT RAND()*100,NAME NVARCHAR(200) DEFAULT 'nihao')
GO


CREATE INDEX IX_RANDTEST_ID ON RANDTEST(ID)
GO




INSERT INTO RANDTEST DEFAULT VALUES
GO 2000


SELECT * FROM RANDTEST

第一種寫法:大家會(huì)想到ORDER BY NEWID()


SET STATISTICS TIME ON
SET STATISTICS IO ON
SELECT TOP 50 [id]  FROM    [dbo].[RANDTEST]
GROUP BY ID
ORDER BY NEWID()
SET STATISTICS TIME OFF
SET STATISTICS IO OFF


這種寫法使用到索引掃描,而且每次select出來的結(jié)果都是一樣的,都是50條記錄




第二種寫法

SET STATISTICS TIME ON
SET STATISTICS IO ON
SELECT TOP 50 [t1].[ID] FROM [dbo].[RANDTEST] t1 JOIN (SELECT RAND()*100 AS nid) t2 ON [t1].[ID]>[t2].[nid]
GROUP BY [t1].[ID]
SET STATISTICS TIME OFF
SET STATISTICS IO OFF


跟t2這個(gè)表做比較,而且每次能夠達(dá)到隨機(jī)取一條或者N條記錄的效果
每次select出來的行數(shù)都是不一樣的


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享分享 分享淘帖 訂閱訂閱

點(diǎn)擊這里給我發(fā)消息

2#
 樓主| 發(fā)表于 2015-10-24 18:34:37 | 只看該作者



比較一下IO和時(shí)間
當(dāng)兩種寫法select出來的結(jié)果條數(shù)都是50條的時(shí)候,時(shí)間和IO都是一樣的,如果第二種寫法select出來的記錄條數(shù)不是50條
那么IO肯定比第一種寫法要少
--第一種寫法  select出來50條記錄SQL Server 執(zhí)行時(shí)間:   CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 0 毫秒。(50 行受影響)表 'RANDTEST'。掃描計(jì)數(shù) 1,邏輯讀取 5 次,物理讀取 0 次,預(yù)讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預(yù)讀 0 次。SQL Server 執(zhí)行時(shí)間:   CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 1 毫秒。--------------------------------------------------------------------------------第二種寫法  select出來37條記錄SQL Server 執(zhí)行時(shí)間:   CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 0 毫秒。(27 行受影響)表 'RANDTEST'。掃描計(jì)數(shù) 1,邏輯讀取 4 次,物理讀取 0 次,預(yù)讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預(yù)讀 0 次。SQL Server 執(zhí)行時(shí)間:   CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 1 毫秒。

總結(jié)
如果第一種寫法寫成下面的樣子,那么每次select出來的結(jié)果都是一樣的,而且不會(huì)進(jìn)行排序,在執(zhí)行計(jì)劃里面你看不到排序這個(gè)運(yùn)算符
因?yàn)榉蔷奂饕桥藕眯虻,掃描非聚集索引只?huì)得到排好序的結(jié)果
SELECT TOP 50 [id  FROM    [dbo.[RANDTESTGROUP BY IDORDER BY RAND()*100


點(diǎn)擊這里給我發(fā)消息

3#
 樓主| 發(fā)表于 2015-10-24 18:34:50 | 只看該作者

綜上,想從SQLSERVER數(shù)據(jù)庫中隨機(jī)取一條或者N條記錄時(shí),最好把RAND()生成隨機(jī)數(shù)放在JOIN子查詢中以提高效率。
SELECT TOP n [id  FROM    tableGROUP BY IDORDER BY NEWID()
改造成下面這個(gè):
SELECT TOP n   [t1.[ID  FROM table  t1 JOIN (SELECT RAND()*100 AS nid) t2 ON [t1.[ID>[t2.[nidGROUP BY [t1.[ID

就可以享受在SQL中直接取得隨機(jī)數(shù)了,不用再在程序中構(gòu)造一串隨機(jī)數(shù)去檢索了。

MYSQL也是同樣的原理
CREATE TABLE `t_innodb_random` (
`id` INT(10) UNSIGNED NOT NULL,
`user` VARCHAR(64) NOT NULL DEFAULT '',
KEY `idx_id` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;




INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('1','lily');
INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('3','tom');
INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('5','fancy');
INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('6','cici');
INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('9','syan');




SELECT * FROM t_innodb_random;




SELECT id FROM t_innodb_random ORDER BY RAND() LIMIT 5;
-- 改造成下面這個(gè):


SELECT id FROM t_innodb_random t1 JOIN (SELECT RAND()*10 AS nid) t2 ON t1.id > t2.nid LIMIT 5;


---------------------------------------------------------------------------------------------


您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則

QQ|站長郵箱|小黑屋|手機(jī)版|Office中國/Access中國 ( 粵ICP備10043721號-1 )  

GMT+8, 2024-10-23 08:39 , Processed in 0.079270 second(s), 26 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回復(fù) 返回頂部 返回列表