我有2张桌子:
第一张表users
:
+-------------------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| first_name | text | NO | | NULL | |
| age | int(11) | YES | | NULL | |
| settings | text | YES | | NULL | |
+-------------------------+---------+------+-----+---------+-------+
第二张表proposals
:
+---------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| from_id | int(11) | NO | | NULL | |
| to_id | int(11) | NO | | NULL | |
| status | int(11) | NO | | NULL | |
+---------+---------+------+-----+---------+----------------+
我需要id
to_id
中proposals
以内SELECT DISTINCT *
FROM profiles
WHERE
profiles.first_name IS NOT NULL
AND
NOT EXISTS (
SELECT *
FROM proposal
WHERE
proposal.to_id = profiles.id
)
LIMIT 0 , 1
以内的用户获取1 随机行
我正在使用这个sql执行它(没有rand):
1 row in set (0.00 sec)
表现很好:1 row in set (1.78 sec)
但性能非常糟糕:ORDER BY RAND()
当我将users.id
添加到最后
我在MAX(id)
中遇到了大漏洞而我无法使用limit
我尝试设置随机...
LIMIT 1234 , 1;
Empty set (2.71 sec)
,例如:
users.id
但它也需要很长时间:(
如何获得具有良好性能的proposals.to_id
中profiles
不存在的随机1位用户?
我认为我需要先使用rand()
获取所有$('.el').click(function(){
var el = this; // assign this to el
my_function(function(){
$(el).hide(); // use el here
});
});
,然后对其进行过滤,但我不知道该怎么做。
答案 0 :(得分:1)
我有两个问题解决方案。
1)随机ID,来自https://stackoverflow.com/a/4329447/2051938
SELECT *
FROM profiles AS r1
JOIN
(SELECT CEIL(RAND() *
(SELECT MAX(id)
FROM profiles)) AS id)
AS r2
WHERE
r1.id >= r2.id
AND
r1.first_name IS NOT NULL
AND
NOT EXISTS (
SELECT *
FROM proposal
WHERE
proposal.to_id = r1.id
)
LIMIT 0 , 1
2)ORDER BY RAND()
SELECT *
FROM
(
SELECT *
FROM profiles
WHERE
profiles.first_name IS NOT NULL
ORDER BY RAND()
) AS users
WHERE
NOT EXISTS (
SELECT *
FROM proposal
WHERE
proposal.to_id = users.id
)
LIMIT 0 , 1
第一种解决方案更快,但id
""漏洞存在问题。当你从最后得到id
时(用户可能会比匹配更早结束)
第二种解决方案速度较慢但没有缺陷!
答案 1 :(得分:0)
您是否尝试将not exists
切换为left join
?
SELECT DISTINCT *
FROM profiles t1
LEFT JOIN
proposal t2
ON t1.id = t2.to_id
WHERE t1.first_name IS NOT NULL AND
t2.to_id IS NULL
ORDER BY RAND()
LIMIT 0 , 1
这会返回profiles
的所有行,并且会向提案行中不是matched
的行返回,它会分配NULL
值,您可以对其进行过滤。
结果应该相同,但性能可能会更好。
答案 2 :(得分:0)
由于RAND()
函数为结果中的每一行指定一个随机数,因此性能将与记录数成正比。
如果您只想选择一条(随机)记录,则可以应用LIMIT <random number from 0 to record count>, 1
e.g:
SELECT u.id, count(u.id) as `count`
FROM users u
WHERE
first_name IS NOT NULL
AND
NOT EXISTS (
SELECT *
FROM proposal
WHERE
proposal.to_id = u.id
)
LIMIT RAND(0, count-1) , 1
我还没有尝试过执行此查询,但是,MySQL
抱怨在count
中使用RAND
,您可以单独计算计数并替换此查询中的值。
答案 3 :(得分:0)
首先,我不认为SELECT p.*
FROM profiles p
WHERE p.first_name IS NOT NULL AND
NOT EXISTS (SELECT 1
FROM proposal pr
WHERE pr.to_id = p.id
)
ORDER BY rand()
LIMIT 0 , 1;
是必要的。所以,尝试删除:
SELECT p.*
FROM profiles
WHERE p.first_name IS NOT NULL AND
NOT EXISTS (SELECT 1
FROM proposal pr
WHERE pr.to_id = p.id
) AND
rand() < 0.01
ORDER BY rand()
LIMIT 0, 1;
这可能会有所帮助。然后,减少花费的时间的相对简单的方法是减少数据量。如果您知道总有数千行符合条件,那么您可以这样做:
SELECT p.*
FROM (SELECT p.*, (@rn := @rn + 1) as rn
FROM profiles p CROSS JOIN
(SELECT @rn := 0) params
WHERE p.first_name IS NOT NULL AND
NOT EXISTS (SELECT 1
FROM proposal pr
WHERE pr.to_id = p.id
)
) p
WHERE rand() < 100 / @rn
ORDER BY rand()
LIMIT 0, 1;
诀窍是找到确保您至少获得一行的比较值。这很棘手,因为你有另一组数据。这是一个使用子查询的方法:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mes="http://www.orange.com/Webalc/Interfaces/ManageSupplierQuote/RequestForQuotation/v3/message">
<soapenv:Header/>
<soapenv:Body>
<mes:UpdateSupplierQuote>
<!--Zero or more repetitions:-->
<SupplierQuote>
<Requester>
<local_userName>anant4</local_userName>
<!--Optional:-->
<local_SalesID></local_SalesID>
<!--Optional:-->
<local_SourcingFTID></local_SourcingFTID>
<!--Optional:-->
<local_AnalystBuyer>Analyst</local_AnalystBuyer>
</Requester>
<!--1 to 100 repetitions:-->
<QuoteItem>
<quoteItemID>m19</quoteItemID>
<simulation_id>10061191</simulation_id>
这使用变量来计算行数,然后随机选择其中的100个进行处理。当随机选择100行时,非常非常非常可能至少选择一行。
这种方法的缺点是子查询需要实现,这会增加查询的成本。然而,它比完整数据的分类便宜。