検索

使用MySQL时需要注意的细节

Jun 07, 2016 pm 04:24 PM
cojoinleftmysql使用知らせ詳細必要

1. LEFT JOIN和COUNT(*) SELECT a.id, COUNT(*) FROM a LEFT JOIN b ON b.a = a.id GROUP BY a.id 这个查询试图统计出对于a中的每条记录来说,在b中匹配的记录的数目。 问题是,在这样一个查询中,COUNT(*)永远不会返回一个0。对于a中某条记录来说,如果没有

1. LEFT JOIN和COUNT(*)

SELECT  a.id, COUNT(*)  
FROM    a  
LEFT JOIN 
        b  
ON      b.a = a.id  
GROUP BY 
        a.id 

这个查询试图统计出对于a中的每条记录来说,在b中匹配的记录的数目。

问题是,在这样一个查询中,COUNT(*)永远不会返回一个0。对于a中某条记录来说,如果没有匹配的记录,那么那条记录还是会被返回和计数。

只有需要统计b中的记录数目的时候才应该使用COUNT。既然可以使用COUNT(*),那么我们也可以使用一个参数来调用它(忽略掉NULL),我们可以把b.a传递给它。在这个例子中,作为一个连接主键,它不可以为空,但是如果不想匹配,它也可以为空。

2. IN和','——值的分隔列表

这个查询试图让column的值匹配用','分隔的字符串中的任意一个值:

SELECT  *  
FROM    a  
WHERE   column IN ('1, 2, 3') 

这不会正常发挥作用的,因为在IN列表中,那个字符串并不会被展开。

如果列column是一个VARCHAR,那么它(作为一个字符串)会和整个列表(也作为一个字符串)进行比较,当然,这不可能匹配。如果 column是某个数值类型,那么这个列表会被强制转换为那种数值类型(在最好的情况下,只有第一项会匹配)。

处理这个查询的正确方法应该是使用合适的IN列表来重写它:

SELECT  *  
FROM    a  
WHERE   column IN (1, 2, 3) 

或者,也可以使用内联:

SELECT  *  
FROM    (  
        SELECT  1 AS id  
        UNION ALL 
        SELECT  2 AS id  
        UNION ALL 
        SELECT  3 AS id  
        ) q  
JOIN    a  
ON      a.column = q.id 

但是,有时这是不可能的。如果不想改变那个查询的参数,可以使用FIND_IN_SET:

SELECT  *  
FROM    a  
WHERE   FIND_IN_SET(column, '1,2,3') 

但是,这个函数不可以利用索引从表中检索行,会在a上执行全表扫描。

3. 通过一个组来选取第一条记录

SELECT  a.*  
FROM    a  
GROUP BY 
        grouper  
ORDER BY 
        MIN(id) DESC 

这个查询试图选出id值最小的记录。但是无法保证通过a.*返回的非聚合的值都属于id值最小的那条记录(或者任意一条记录)。

这样做会更清晰一些:

SELECT  a.*  
FROM    (  
        SELECT  DISTINCT grouper  
       FROM    a  
        ) ao  
JOIN    a  
ON      a.id =  
        (  
        SELECT  id  
        FROM    a ai  
        WHERE   ai.grouper = ao.grouper  
        ORDER BY 
                ai.grouper, ai.id  
        LIMIT 1  
        ) 

这个查询和前面那个查询类似,但是使用额外的ORDER BY可以确保按id来排序的第一条记录会被返回。

4. 通过一个组来选取任意的记录

这个查询打算通过某个组(定义为grouper来)来选出一些记录:

SELECT  DISTINCT(grouper), a.*  
FROM    a 

DISTINCT不是一个函数,它是SELECT子句的一部分。它会应用到SELECT列表中的所有列,实际上,这里的括号是可以省略的。所以,这个查询可能会选出grouper中的值都相同的记录(如果在其他列中,至少有一个列的值是不同的)。

有时,这个查询可以正常地使用( 这主要依赖于MySQL对GROUP BY的扩展):

SELECT  a.*  
FROM    a  
GROUP BY 
        grouper 

在某个组中返回的非聚合的列可以被任意地使用。

首先,这似乎是一个很好的解决方案,但是,它存在着一个很严重的缺陷。它依赖于这样一个假设:虽然可以通过组来任意地获取,但是返回的所有值都要属于一条记录。

虽然当前的实现似乎就是这样的,但是它并没有文档化,无论何时,它都有可能被改变(尤其是,当MySQL学会了在GROUP BY的后面使用index_union的时候)。所以依赖于这个行为并不安全。

如果MySQL支持分析函数的话,这个查询可以很容易地用另一种更清晰的方式来重写。但是,如果这张表拥有一个PRIMARY KEY的话,即使不使用分析函数,也可以做到这一点:

SELECT  a.*  
FROM    (  
        SELECT  DISTINCT grouper  
        FROM    a  
        ) ao  
JOIN    a  
ON      a.id =  
        (  
        SELECT  id  
       FROM    a ai  
        WHERE   ai.grouper = ao.grouper  
        LIMIT 1  
        ) 

5. 对随机的样本进行排序

SELECT  *  
FROM    a  
ORDER BY 
        RAND(), column 
LIMIT 10 

这个查询试图选出10个随机的记录,按照column来排序。

ORDER BY会按照自然顺序来对输出结果进行排序:这就是说,当第一个表达式的值相等的时候,这些记录才会按照第二个表达式来排序。

但是,RAND()的结果是随机的。要让RAND()的值相等是行不通的,所以,按照RAND()排序以后,再按照column来排序也是没有意义的。

要对随机的样本记录进行排序,可以使用这个查询:

SELECT  *  
FROM    (  
        SELECT  *  
        FROM    mytable  
        ORDER BY 
                RAND()  
        LIMIT 10  
       ) q  
ORDER BY 
       column 

6. NOT IN和NULL值

SELECT  a.*  
FROM    a  
WHERE   a.column NOT IN 
        (  
        SELECT column 
        FROM    b  
        ) 

如果在b.column中有一个NULL值,那么这个查询是不会返回任何结果的。和其他谓词一样,IN 和 NOT IN 遇到NULL也会被判定为NULL。

你应该使用NOT EXISTS重写这个查询:

SELECT  a.*  
FROM    a  
WHERE   NOT EXISTS  
        (  
        SELECT NULL 
        FROM    b  
       WHERE   b.column = a.column 
       ) 

不像IN,EXISTS总是被判定为true或false的。

7. 按照NULL来进行连接

SELECT  *  
FROM    a  
JOIN    b  
ON      a.column = b.column 

在两个表中,当column是nullable的时候,这个查询不会返回两个字段都是NULL的记录,原因如上所述:两个NULL并不相等。

这个查询应该这样来写:

SELECT  *  
FROM    a  
JOIN    b  
ON      a.column = b.column 
        OR (a.column IS NULL AND b.column IS NULL) 

MySQL的优化器会把这个查询当成一个"等值连接",然后提供一个特殊的连接条件:ref_or_null。

8. 小于一个值,但是不为NULL

我经常看到这样的查询:

SELECT  *  
FROM    b  
WHERE   b.column < 'something' 
       AND b.column IS NOT NULL 

实际上,这并不是一个错误:这个查询是有效的,是故意这样做的。但是,这里的IS NOT NULL是冗余的。

如果b.column是NULL,那么无法满足b.column

有趣的是,这个附加的NULL检查不能和"大于"查询(例如:b.column > 'something')一起使用。

这是因为,在MySQL中,在ORDER BY的时候,NULL会排在前面,因此,一些人错误地认为NULL比任何其他的值都要小。

这个查询可以被简化:

SELECT  *  
FROM    b  
WHERE   b.column < 'something' 

在b.column中,不可能返回NULL。

9. 使用附加条件的LEFT JOIN

SELECT  *  
FROM    a  
LEFT JOIN 
        b  
ON      b.a = a.id  
WHERE   b.column = 'something' 

除了从a返回每个记录(至少一次),当没有真正匹配的记录的时候,用NULL值代替缺失的字段之外,LEFT JOIN和INNER JOIN都是一样的。

但是,在LEFT JOIN之后才会检查WHERE条件,所以,上面这个查询在连接之后才会检查column。就像我们刚才了解到的那样,非NULL值才可以满足相等条件,所以,在a的记录中,那些在b中没有对应的条目的记录不可避免地要被过滤掉。

从本质上来说,这个查询是一个INNER JOIN,只是效率要低一些。

为了真正地匹配满足b.column = 'something'条件的记录(这时要返回a中的全部记录,也就是说,不过滤掉那些在b中没有对应的条目的记录),这个条件应该放在ON子句中:

SELECT  *  
FROM    a  
LEFT JOIN 
        b  
ON      b.a = a.id  
        AND b.column = 'something' 

10. 搜索一个"NULL"值

SELECT  *  
FROM    a  
WHERE   a.column = NULL 

在SQL中,NULL什么也不等于,而且NULL也不等于NULL。这个查询不会返回任何结果的,实际上,当构建那个plan的时候,优化器会把这样的语句优化掉。

当搜索NULL值的时候,应该使用这样的查询:

SELECT  *  
FROM    a  
WHERE   a.column IS NULL 
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
MySQL Index Cardinalityはクエリパフォーマンスにどのように影響しますか?MySQL Index Cardinalityはクエリパフォーマンスにどのように影響しますか?Apr 14, 2025 am 12:18 AM

MySQLインデックスのカーディナリティは、クエリパフォーマンスに大きな影響を及ぼします。1。高いカーディナリティインデックスは、データ範囲をより効果的に狭め、クエリ効率を向上させることができます。 2。低カーディナリティインデックスは、完全なテーブルスキャンにつながり、クエリのパフォーマンスを削減する可能性があります。 3。ジョイントインデックスでは、クエリを最適化するために、高いカーディナリティシーケンスを前に配置する必要があります。

MySQL:新規ユーザー向けのリソースとチュートリアルMySQL:新規ユーザー向けのリソースとチュートリアルApr 14, 2025 am 12:16 AM

MySQL学習パスには、基本的な知識、コアの概念、使用例、最適化手法が含まれます。 1)テーブル、行、列、SQLクエリなどの基本概念を理解します。 2)MySQLの定義、作業原則、および利点を学びます。 3)インデックスやストアドプロシージャなどの基本的なCRUD操作と高度な使用法をマスターします。 4)インデックスの合理的な使用や最適化クエリなど、一般的なエラーのデバッグとパフォーマンス最適化の提案に精通しています。これらの手順を通じて、MySQLの使用と最適化を完全に把握できます。

実際のmysql:例とユースケース実際のmysql:例とユースケースApr 14, 2025 am 12:15 AM

MySQLの実際のアプリケーションには、基本的なデータベース設計と複雑なクエリの最適化が含まれます。 1)基本的な使用法:ユーザー情報の挿入、クエリ、更新、削除など、ユーザーデータの保存と管理に使用されます。 2)高度な使用法:eコマースプラットフォームの注文や在庫管理など、複雑なビジネスロジックを処理します。 3)パフォーマンスの最適化:インデックス、パーティションテーブル、クエリキャッシュを使用して合理的にパフォーマンスを向上させます。

MySQLのSQLコマンド:実用的な例MySQLのSQLコマンド:実用的な例Apr 14, 2025 am 12:09 AM

MySQLのSQLコマンドは、DDL、DML、DQL、DCLなどのカテゴリに分割でき、データベースとテーブルの作成、変更、削除、データの挿入、更新、削除、複雑なクエリ操作の実行に使用できます。 1.基本的な使用には、作成可能な作成テーブル、INSERTINTO INSERTデータ、クエリデータの選択が含まれます。 2。高度な使用法には、テーブル結合、サブQueries、およびデータ集約のためのグループに参加します。 3.構文エラー、データ型の不一致、許可の問題などの一般的なエラーは、構文チェック、データ型変換、許可管理を介してデバッグできます。 4.パフォーマンス最適化の提案には、インデックスの使用、フルテーブルスキャンの回避、参加操作の最適化、およびデータの一貫性を確保するためのトランザクションの使用が含まれます。

InnoDBは酸コンプライアンスをどのように処理しますか?InnoDBは酸コンプライアンスをどのように処理しますか?Apr 14, 2025 am 12:03 AM

INNODBは、ロックメカニズムとMVCCを通じて、非論的、一貫性、および分離を通じて原子性を達成し、レッドログを介した持続性を達成します。 1)原子性:Undologを使用して元のデータを記録して、トランザクションをロールバックできることを確認します。 2)一貫性:行レベルのロックとMVCCを介してデータの一貫性を確保します。 3)分離:複数の分離レベルをサポートし、デフォルトでrepeatable -readが使用されます。 4)持続性:Redologを使用して修正を記録し、データが長時間保存されるようにします。

MySQLの場所:データベースとプログラミングMySQLの場所:データベースとプログラミングApr 13, 2025 am 12:18 AM

データベースとプログラミングにおけるMySQLの位置は非常に重要です。これは、さまざまなアプリケーションシナリオで広く使用されているオープンソースのリレーショナルデータベース管理システムです。 1)MySQLは、効率的なデータストレージ、組織、および検索機能を提供し、Web、モバイル、およびエンタープライズレベルのシステムをサポートします。 2)クライアントサーバーアーキテクチャを使用し、複数のストレージエンジンとインデックスの最適化をサポートします。 3)基本的な使用には、テーブルの作成とデータの挿入が含まれ、高度な使用法にはマルチテーブル結合と複雑なクエリが含まれます。 4)SQL構文エラーやパフォーマンスの問題などのよくある質問は、説明コマンドとスロークエリログを介してデバッグできます。 5)パフォーマンス最適化方法には、インデックスの合理的な使用、最適化されたクエリ、およびキャッシュの使用が含まれます。ベストプラクティスには、トランザクションと準備された星の使用が含まれます

MySQL:中小企業から大企業までMySQL:中小企業から大企業までApr 13, 2025 am 12:17 AM

MySQLは、中小企業に適しています。 1)中小企業は、顧客情報の保存など、基本的なデータ管理にMySQLを使用できます。 2)大企業はMySQLを使用して、大規模なデータと複雑なビジネスロジックを処理して、クエリのパフォーマンスとトランザクション処理を最適化できます。

Phantomの読み取りとは何ですか?Innodbはどのようにそれらを防ぐ(次のキーロック)?Phantomの読み取りとは何ですか?Innodbはどのようにそれらを防ぐ(次のキーロック)?Apr 13, 2025 am 12:16 AM

INNODBは、次のキーロックメカニズムを通じてファントムの読み取りを効果的に防止します。 1)Next-KeyLockingは、Row LockとGap Lockを組み合わせてレコードとギャップをロックして、新しいレコードが挿入されないようにします。 2)実際のアプリケーションでは、クエリを最適化して分離レベルを調整することにより、ロック競争を削減し、並行性パフォーマンスを改善できます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境