شنبه ۲۲ شهریور ۱۴۰۴

Saturday, September 13, 2025 GMT +3:30

محدودسازی، گروه بندی و مرتب سازی نتایج در MySQL

mysql-order-group

در مبحث قبل از بخش آموزش مقدماتی MySQL در خصوص نحوه استفاده از دستور WHERE برای تعیین آدرس دقیق ردیف ها و بدست آوردن نتایج مورد نظر از دیتابیس توضیحاتی ارائه شد، در ادامه این مباحث و در این آموزش می خواهیم دیگر پارامترهای وابسته به دستور WHERE را بررسی کنیم که هدف های دیگری از جمله محدودسازی، گروه بندی و مرتب سازی نتایج پرس و جوها را محقق می کنند، منظور از این اصطلاحات تعیین تعداد ردیف های خروجی یا محدود کردن دامنه انتخاب نتایج، گروه بندی ردیف های با مقدار مشابه و مرتب سازی نتایج به فرض بر اساس حروف الفبا یا مقایسه مقادیر عددی (کوچکتر بزرگتر) است، در زبان SQL (که در MySQL از آن برای نگارش و پردازش پرس و جوها استفاده می کنیم) برای این هدف ها دستورات خاصی در نظر گرفته شده از جمله LIMIT برای محدودسازی، GROUP BY برای گروه بندی ستون های یکسان، HAVING برای تعیین شرط، DISTINCT برای حذف موارد تکراری و ORDER BY برای مرتب سازی (Sorting) نتایج که در ادامه در خصوص هر کدام از این پارامترها و چند پارامتر مرتبط دیگر شامل ASC، DESC، RAND، AND، OR، IN و BETWEEN به همراه نمونه کد توضیح خواهیم داد.

ساخت دیتابیس، جدول و ورود نمونه اطلاعات


قبل از پرداختن به مباحث اصلی آموزش ابتدا با استفاده از برنامه phpMyAdmin یک دیتابیس با نام دلخواه (ترجیحا Collation به صورت utf8_persian_ci) و دو جدول فرضی با نام های tbl_1_name و tbl_2_name با نمونه ردیف های زیر در آن ایجاد می کنیم، برای جدول tbl_1_name:
id  =>  int(11) AUTO_INCREMENT
name  =>  varchar(255)
age  =>  int(11)
point  =>  int(11)
هم به صورت دستی و هم با اجرای دستورات زیر در قسمت SQL برنامه phpMyAdmin می توانیم جدول بالا را ایجاد کنیم:
CREATE TABLE IF NOT EXISTS `tbl_1_name` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_persian_ci DEFAULT NULL,
  `age` int(11) UNSIGNED DEFAULT NULL,
  `point` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci;
و برای جدول tbl_2_name:
id  =>  int(11) AUTO_INCREMENT
name  =>  varchar(255)
برای ساخت این جدول هم علاوه بر شیوه دستی می توانیم در قسمت SQL برنامه phpMyAdmin دستورات زیر را اجرا کنیم:
CREATE TABLE IF NOT EXISTS `tbl_2_name` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_persian_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci;
نکته مهم: با توجه به اینکه ممکن است در آینده حروف زبان فارسی را در دیتابیس ذخیره یا از آن دریافت کنیم توصیه می شود Collation دیتابیس و جداول را در برنامه phpMyAdmin به صورت utf8_persian_ci تنظیم کنیم.
برای اینکه نمونه اطلاعاتی جهت تست و بررسی در اختیار داشته باشیم دستورات زیر را در قسمت SQL برنامه phpMyAdmin برای جدول tbl_1_name و tbl_2_name اجرا می کنیم، برای جدول tbl_1_name:
INSERT INTO `tbl_1_name` (`id`, `name`, `age`, `point`) VALUES
(1, 'A', 20, 12),
(2, 'B', 13, 15),
(3, 'C', 15, 33),
(4, 'D', 23, 12),
(5, 'E', 12, 13),
(6, 'F', 16, 35);
و برای جدول tbl_2_name:
INSERT INTO `tbl_2_name` (`id`, `name`) VALUES
(1, 'A'),
(2, 'C');
یا اینکه می توانیم کدهای زیر را در یک فایل PHP درج و با انجام تنظیمات اتصال به دیتابیس در قسمت متغیر conn، فایل PHP را در مرورگر فراخوانی و اجرا کنیم.
برنامه نویسی رویه ای (Procedural):
<?php
$array = array(
    'name' => array('A', 'B', 'C', 'D', 'E', 'F'),
    'age' => array(20, 13, 15, 23, 12, 16),
    'point' => array(12, 15, 33, 12, 13, 35)
);
$count = count($array['name']);
//اتصال به دیتابیس
$conn = mysqli_connect("localhost", "username", "password", "dbname");
if(!$conn){
    echo "PHP & MySQL Connection: Error! " . mysqli_connect_errno() . ' - ' . mysqli_connect_error();
    exit;
} else {
    //ذخیره نمونه اطلاعات در جدول
    for($i = 0; $i < $count; $i++){
        $sql = "INSERT INTO tbl_1_name(name, age, point) VALUES('" . $array['name'][$i] . "', '" . $array['age'][$i] . "', '" . $array['point'][$i] . "')";
        $query = mysqli_query($conn, $sql);
         
        if(!$query) {
            echo "Inserting Into Table tbl_1_name: Error! " . mysqli_error($conn);
            break;
        } else {
            echo "tbl_1_name: Row " . ($i + 1) . " Inserted!<br>";
        }
    }
    
    $sql = "INSERT INTO tbl_2_name(name) VALUES('" . $array['name'][0] . "')";
    $query = mysqli_query($conn, $sql);
    
    if(!$query) {
        echo "Inserting Into Table tbl_2_name: Error! " . mysqli_error($conn) . '<br>';
    } else {
        echo "tbl_2_name: Row 1 Inserted!<br>";
    }
    
    $sql = "INSERT INTO tbl_2_name(name) VALUES('" . $array['name'][2] . "')";
    $query = mysqli_query($conn, $sql);
    
    if(!$query) {
        echo "Inserting Into Table tbl_2_name: Error! " . mysqli_error($conn) . '<br>';
    } else {
        echo "tbl_2_name: Row 2 Inserted!<br>";
    }
}
//پایان اتصال
mysqli_close($conn);
?>
برنامه نویسی شی گرا (Object-oriented):
<?php
$array = array(
    'name' => array('A', 'B', 'C', 'D', 'E', 'F'),
    'age' => array(20, 13, 15, 23, 12, 16),
    'point' => array(12, 15, 33, 12, 13, 35)
);
$count = count($array['name']);
//اتصال به دیتابیس
$conn = new mysqli("localhost", "username", "password", "dbname");
if(!$conn){
    echo "PHP & MySQL Connection: Error! " . $conn->errno . ' - ' . $conn->error;
    exit;
} else {
    //ذخیره نمونه اطلاعات در جدول
    for($i = 0; $i < $count; $i++){
        $sql = "INSERT INTO tbl_1_name(name, age, point) VALUES('" . $array['name'][$i] . "', '" . $array['age'][$i] . "', '" . $array['point'][$i] . "')";
        $query = $conn->query($sql);
         
        if(!$query) {
            echo "Inserting Into Table tbl_1_name: Error! " . $conn->error;
            break;
        } else {
            echo "tbl_1_name: Row " . ($i + 1) . " Inserted!<br>";
        }
    }
    
    $sql = "INSERT INTO tbl_2_name(name) VALUES('" . $array['name'][0] . "')";
    $query = $conn->query($sql);
    
    if(!$query) {
        echo "Inserting Into Table tbl_2_name: Error! " . $conn->error . '<br>';
    } else {
        echo "tbl_2_name: Row 1 Inserted!<br>";
    }
    
    $sql = "INSERT INTO tbl_2_name(name) VALUES('" . $array['name'][2] . "')";
    $query = $conn->query($sql);
    
    if(!$query) {
        echo "Inserting Into Table tbl_2_name: Error! " . $conn->error . '<br>';
    } else {
        echo "tbl_2_name: Row 2 Inserted!<br>";
    }
}
//پایان اتصال
$conn->close();
?>
در نهایت اطلاعات جدول tbl_1_name باید به صورت زیر باشد:
id      name      age      point
1        A        20        12
2        B        13        15
3        C        15        33
4        D        23        12
5        E        12        13
6        F        16        35
و اطلاعات جدول tbl_2_name نیز به صورت زیر باشد:
id     name
1       A
2       C
از ساختار و اطلاعات این نمونه جداول برای تست و بررسی پارامترهایی که در ادامه خواهیم گفت استفاده می کنیم.

استفاده از LIMIT


اجرای پرس و جوهای هرچند ساده با استفاده از دستور WHERE به تنهایی و بدون محدود کردن تعداد نتایج با پارامترهای اضافه می تواند منجر به دریافت حجم زیادی از اطلاعات ناخواسته شود که قطعا حالت بهینه نیست و احتمالا باعث کندی برنامه و فشار بی دلیل بر پایگاه داده خواهد شد، از این رو در زبان SQL برای WHERE پارامترهای محدود کننده ای مانند LIMIT در نظر گرفته اند، دستور LIMIT تعداد ردیف های نتایج به دست آمده از اجرای پرس و جوهای دیتابیس را به موارد مشخصی محدود می کند، به فرض در پرس و جوی فرضی زیر صرفا 3 ردیف از اطلاعات به عنوان خروجی درخواست برگردانده می شود:
SELECT * FROM tbl_1_name WHERE name != '' LIMIT 3

id      name      age      point
1        A        20        12
2        B        13        15
3        C        15        33
علاوه بر تعیین تعداد ردیف ها می توانیم نقطه شروع انتخاب ردیف ها را هم برای MySQL مشخص کنیم که در این صورت برای LIMIT از دو پارامتر عددی استفاده می کنیم، عدد اول شماره ردیف برای تعیین نقطه آغاز دریافت نتایج و عدد دوم تعداد نتایجی است که پرس و جو را به آن محدود کرده ایم، به طور مثال در نمونه کد زیر از ردیف 2 به بعد 3 ردیف به عنوان نتیجه برگردانده می شود (شامل خود ردیف دوم نمی شود):
SELECT * FROM tbl_1_name WHERE name != '' LIMIT 2, 3

id      name      age      point
3        C        15        33
4        D        23        12
5        E        12        13
با استفاده از این شیوه می توانیم به صورت داینامیک قابلیت هایی مانند صفحه بندی محتوا را در برنامه های وب ایجاد کنیم که در آموزش های کاربردی MySQL در این خصوص خواهیم گفت، برای تست و بررسی دستور LIMIT کافی است پرس و جوهای بالا را در قسمت SQL برنامه phpMyAdmin اجرا یا کد زیر را در یک فایل PHP درج و پس از اعمال تنظیمات اتصال در متغیر conn از طریق مرورگر فراخوانی کنیم.
 برنامه نویسی رویه ای (Procedural):
<?php
//اتصال به دیتابیس
$conn = mysqli_connect("localhost", "username", "password", "dbname");
if(!$conn){
    echo "PHP & MySQL Connection: Error! " . mysqli_connect_errno() . ' - ' . mysqli_connect_error();
    exit;
} else{    
    //سازگاری با حروف فارسی
    $sql = "SET NAMES 'utf8'";
    $query = mysqli_query($conn, $sql);
    
    //اانتخاب اطلاعات از جدول و ستون ها
    $sql = "SELECT name, age, point FROM tbl_1_name WHERE name != '' LIMIT 2, 3";
    $query = mysqli_query($conn, $sql);
    
    if(!$query){
        echo "Selecting From Table tbl_1_name: Error! " . mysqli_error($conn) . '<br>';
    } else{
        //تعداد ردیف های انتخاب شده
        $count = mysqli_num_rows($query);
        $loop = 1;
        
        //پردازش و خروجی ردیف های اطلاعات
        if($count > 0){
            echo '<div style="direction: ltr; border: 1px solid #999;">';
            
            echo 'Row Count: ' . $count . '<br><br>';
            while($row = mysqli_fetch_array($query)){
                echo 'Row ' . $loop . ' => ' .
                'Name: ' . $row['name'] . ' - ' .
                'Age: ' . $row['age'] . ' - ' .
                'Point: ' . $row['point'] . '<br><br>';
                
                $loop++;
            }
            
            echo '</div>';
        } else{
            echo "No Rows Found in Table tbl_1_name!";
        }
    }
}
//پایان اتصال
mysqli_close($conn);
?>
برنامه نویسی شی گرا (Object-oriented):
<?php
//اتصال به دیتابیس
$conn = new mysqli("localhost", "username", "password", "dbname");
if(!$conn){
    echo "PHP & MySQL Connection: Error! " . $conn->errno . ' - ' . $conn->error;
    exit;
} else {
    //سازگاری با حروف فارسی
    $sql = "SET NAMES 'utf8'";
    $conn->query($sql);
    
    //اانتخاب اطلاعات از جدول و ستون ها
    $sql = "SELECT name, age, point FROM tbl_1_name WHERE name != '' LIMIT 2, 3";
    $query = $conn->query($sql);
    
    //دریافت اطلاعات از جدول
    if(!$query) {
        echo "Selecting From Table tbl_1_name: Error! " . $conn->error . '<br>';
    } else {
        //تعداد ردیف های انتخاب شده
        $count = $query->num_rows;
        $loop = 1;
        
        //پردازش و خروجی ردیف های اطلاعات
        if($count > 0){
            echo '<div style="direction: ltr; border: 1px solid #999;">';
            
            echo 'Row Count: ' . $count . '<br><br>';
            while($row = $query->fetch_array()){
                echo 'Row ' . $loop . ' => ' .
                'Name: ' . $row['name'] . ' - ' .
                'Age: ' . $row['age'] . ' - ' .
                'Point: ' . $row['point'] . '<br><br>';
                
                $loop++;
            }
            
            echo '</div>';
        } else{
            echo "No Rows Found in Table tbl_1_name!";
        }
    }
}
//پایان اتصال
$conn->close();
?>
خروجی نمونه کدهای بالا به صورت زیر خواهد بود:
Row Count: 3
Row 1 => Name: C - Age: 15 - Point: 33
Row 2 => Name: D - Age: 23 - Point: 12
Row 3 => Name: E - Age: 12 - Point: 13
همان طور که مشخص است از ردیف دوم به بعد 3 ردیف انتخاب شده اند.

استفاده از GROUP BY


یک قابلیت کاربردی دیگر که در زمینه دسته بندی و نمایش بهتر نتایج حاصل از اجرای پرس و جوهای پایگاه داده MySQL می توانیم از آن استفاده کنیم قابلیت گروه بندی نتایج دارای مقادیر مشترک با GROUP BY و خلاصه کردن نتیجه در یک ردیف است، به فرض در نمونه اطلاعاتی که در دیتابیس بالا درج کرده ایم در جدول tbl_1_name دو ردیف 1 و 4 دارای point یکسان هستند و بر این اساس می توانیم نمونه پرس و جوی متغیر sql را به صورت زیر بنویسیم:
SELECT name, age, point FROM tbl_1_name WHERE name != '' GROUP BY point
با اجرای کدها خروجی به صورت نمونه زیر خواهد بود:
Row Count: 5
Row 1 => Name: A - Age: 20 - Point: 12
Row 2 => Name: E - Age: 12 - Point: 13
Row 3 => Name: B - Age: 13 - Point: 15
Row 4 => Name: C - Age: 15 - Point: 33
Row 5 => Name: F - Age: 16 - Point: 35
با در نظر گرفتن دستور GROUP BY برای ستون دارای مقدار مشترک (در اینجا point) تمام ردیف ها در یک ردیف خلاصه می شوند، اگر در نتایج به دست آمده دقت کنیم GROUP BY صرفا در خلاصه کردن نتیجه بدست آمده تاثیرگذار نیست و نحوه چینش را هم بر اساس ستون در نظر گرفته شده تغییر می دهد.

استفاده از HAVING


به همراه گروه بندی با دستور GROUP BY می توانیم با HAVING (برگرفته از have به معنی داشتن) شرط مضاعف تعیین کنیم، به طور مثال می خواهیم در پرس و جوی بالا فقط ردیف هایی را در نتایج داشته باشیم که میزان ردیف سن از 15 بیشتر باشد، برای این منظور می توانیم نمونه پرس و جوی متغیر sql را به صورت زیر بنویسیم:
SELECT name, age, point FROM tbl_1_name WHERE name != '' GROUP BY point HAVING age > 15
با اجرای کدها خروجی به صورت نمونه زیر خواهد بود:
Row Count: 2
Row 1 => Name: A - Age: 20 - Point: 12
Row 2 => Name: F - Age: 16 - Point: 35
استفاده از HAVING می تواند به همراه توابع تجمیعی (مانند SUM) باشد که در این خصوص در آموزش پیش رو به صورت اختصاصی صحبت خواهیم کرد.

استفاده از DISTINCT


عبارت DISTINCT به معنی جداسازی و افتراق است و برای اینکه نتایج تکراری را در پرس و جوهای MySQL نداشته باشیم می توانیم از این دستور استفاده کنیم، ممکن است DISTINCT و GROUP BY نتیجه مشابهی داشته باشند اما با دو هدف متفاوت در موتور MySQL تعریف شده اند و در مراحل متفاوتی پردازش می شوند:
- DISTINCT در مرحله انتخاب ردیف ها حذف موارد تکراری را اعمال می کند.
- GROUP BY پس از انتخاب ردیف ها گروه بندی نتایج یکسان را انجام می دهد.
این دو کارکرد متفاوت در هنگام نوشتن پرس و جوهای پیشرفته و چندبخشی به طور مثال در ترکیب با توابع تجمیعی (در آموزش بعدی توضیح خواهیم داد) این امکان را فراهم می کنند که در مراحل مختلف پردازش پرس و جو دستورات متفاوتی را با هم استفاده و نتایج دقیق و و یکتا (Unique) به دست آوریم.
برای آشنایی بیشتر با نحوه کار دستور DISTINCT در نمونه اطلاعاتی که در دیتابیس بالا درج کرده ایم در جدول tbl_1_name دو ردیف 1 و 4 دارای point یکسان هستند و بر این اساس می توانیم نمونه پرس و جوی متغیر sql را به صورت زیر بنویسیم:
SELECT DISTINCT point FROM tbl_1_name WHERE name != ''
با اجرای کدها و اصلاح قسمت while به این شکل:
while($row = mysqli_fetch_array($query)){
    echo 'Row ' . $loop . ' => ' .
    'Point: ' . $row['point'] . '<br><br>';
    
    $loop++;
}
ردیف دوم با مقدار point 12 حذف و خروجی به صورت نمونه زیر خواهد بود:
Row Count: 5
Row 1 => Point: 12
Row 2 => Point: 13
Row 3 => Point: 15
Row 4 => Point: 33
Row 5 => Point: 35
اگر برای دستور DISTINCT چند ستون در نظر بگیریم، به فرض:
SELECT DISTINCT point, name FROM tbl_1_name WHERE name != ''
هر دو ستون (point و name) باید در یک ردیف شامل مقدار مشترک باشند تا در نتیجه پرس و جو ردیف های تکراری آنها حذف شود در غیر اینصورت به فرض اگر فقط یک ستون دارای مقدار مشترک باشد عمل حذف ردیف تکراری انجام نمی شود.

استفاده از ORDER BY


در بسیاری از برنامه ها و صفحات وب نیاز به مرتب سازی و استخراج نتایج سفارشی از پایگاه داده به فرض بر اساس شماره ID، به ترتیب حروف الفبا، طبق تاریخ، بر اساس بزرگتر کوچکتری مقادیر ستون های عددی و مواردی از این قبیل وجود دارد که به همین دلیل پارامتر دیگری تحت عنوان ORDER BY در زبان SQL در نظر گرفته شده است، با استفاده از این دستور در کنار WHERE می توانیم نتایج سفارشی از پرس و جوها استخراج یا آنها را مرتب سازی کنیم، به فرض اگر بخواهیم نتایج پرس و جو در نمونه دیتابیس بالا بر اساس سن کاربران از بزرگتر به کوچکتر دریافت و چینش شوند می توانیم متغیر sql را به شکل زیر تغییر دهیم:
SELECT name, age, point FROM tbl_1_name WHERE name != '' ORDER BY age LIMIT 3
با اجرای کدها خروجی به صورت نمونه زیر خواهد بود:
Row Count: 3
Row 1 => Name: E - Age: 12 - Point: 13
Row 2 => Name: B - Age: 13 - Point: 15
Row 3 => Name: C - Age: 15 - Point: 33
با دقت در نحوه چینش ردیف ها مشخص است که اطلاعات بر اساس سن (مقادیر ستون age) از کوچکتر به بزرگتر انتخاب و مرتب سازی شده اند.

استفاده از ASC، DESC و تابع RAND


در حالت پیش فرض MySQL نتایج را به صورت صعودی (از کوچک به بزرگ یا Ascending) مرتب سازی می کند، اما مرتب سازی به صورت نزولی (از بزرگ به کوچک یا Descending) و همچنین انتخاب اتفاقی (تصادفی یا Random) با افزودن عباراتی که در ادامه بررسی می کنیم امکانپذیر است، برای تعیین نوع انتخاب و مرتب سازی می توانیم یکی از پارامترهای زیر را در کنار دستور ORDER BY استفاده کنیم:
ASC: استخراج و مرتب سازی پیش فرض یا صعودی (از کوچک به بزرگ)
DESC: استخراج و مرتب سازی نزولی (از بزرگ به کوچک)
RAND: استخراج و مرتب سازی به صورت اتفاقی (تصادفی)
بر این اساس کدی که در بالا نوشتیم را می توانیم به صورت های زیر ویرایش و چینش نتایج حاصل از اجرای پرس و جو را به شکل سفارشی و دلخواه تغییر دهیم.
تغییر پرس و جو با استفاده از ASC برای استخراج و نمایش نتایج به صورت چینش صعودی (حالت پیش فرض):
SELECT name, age, point FROM tbl_1_name WHERE name != '' ORDER BY age ASC LIMIT 3
نمونه خروجی:
Row Count: 3
Row 1 => Name: E - Age: 12 - Point: 13
Row 2 => Name: B - Age: 13 - Point: 15
Row 3 => Name: C - Age: 15 - Point: 33
تغییر پرس و جو با استفاده از DESC برای استخراج و نمایش نتایج به صورت چینش نزولی:
SELECT name, age, point FROM tbl_1_name WHERE name != '' ORDER BY age DESC LIMIT 3
نمونه خروجی:
Row Count: 3
Row 1 => Name: D - Age: 23 - Point: 12
Row 2 => Name: A - Age: 20 - Point: 12
Row 3 => Name: F - Age: 16 - Point: 35
همانطور که مشخص است ردیف ها بر اساس بیشترین مقدار ستون age انتخاب و مرتب سازی شده اند.
تغییر پرس و جو با استفاده از تابع RAND برای استخراج و نمایش نتایج به صورت چینش اتفاقی (تصادفی):
SELECT name, age, point FROM tbl_1_name WHERE name != '' ORDER BY RAND() LIMIT 3
نمونه خروجی:
Row Count: 3
Row 1 => Name: A - Age: 20 - Point: 12
Row 2 => Name: D - Age: 23 - Point: 12
Row 3 => Name: E - Age: 12 - Point: 13
با دقت در کدها مشخص است که نام هیچ ستونی پس از ORDER BY درج نشده و برای RAND هم از کاراکترهای () استفاده کرده ایم، این کار به دلیل تابع بودن RAND در MySQL است به عبارتی ماهیتا این پارامتر با پارامترهای دیگر متفاوت است و باید Syntax صحیح را در نگارش پرس و جو رعایت کنیم تا برنامه با خطا مواجه نشود.

استفاده از AND و OR


در آموزش های مقدماتی زبان PHP با کاربرد کاراکترهای && و || برای سخت و محدود کردن یا بسط دامنه شمول مقایسه های شرطی آشنا شدیم، گفتیم که در برنامه نویسی اگر بخواهیم شرط را سخت و محدود به بررسی پارامترهای بیشتر کنیم از کاراکتر && و اگر بخواهیم دامنه شمول کدهایمان را بسط داده و با تحقق یکی از شرایط، مقایسه برقرار باشد از کاراکتر || استفاده می کنیم، مشابه این مبحث در نوشتن پرس و جوهای MySQL نیز با دستورات AND (به معنی 'و') و OR (به معنی 'یا') قابل استفاده است، از دستور AND برای محدود کردن هرچه بیشتر ردیف های انتخابی و از OR برای بسط پرس و جو و انتخاب ردیف ها با تحقق یکی از شرایط بهره می گیریم.
به طور مثال اگر بخواهیم از نمونه جدول بالا اسامی را استخراج کنیم که age آنها از 15 بزرگتر و point آنها از 15 کوچکتر باشد خواهیم نوشت:
SELECT name, age, point FROM tbl_1_name WHERE name != '' AND age > 15 AND point < 15
دستور بالا کاربرانی را که سن آنها بالاتر از 15 و امتیاز کسب شده کمتر از 15 باشد را در لیست نتایج پرس و جو نمایش می دهد:
Row Count: 2
Row 1 => Name: A - Age: 20 - Point: 12
Row 2 => Name: D - Age: 23 - Point: 12
همین پرس و جو را اگر با OR بنویسیم خروجی متفاوت خواهد بود:
SELECT name, age, point FROM tbl_1_name WHERE name != '' AND age > 15 OR point < 15

Row Count: 4
Row 1 => Name: A - Age: 20 - Point: 12
Row 2 => Name: D - Age: 23 - Point: 10
Row 3 => Name: E - Age: 12 - Point: 13
Row 4 => Name: F - Age: 16 - Point: 35
در این حالت ردیف هایی از دیتابیس انتخاب می شوند که یا age آنها از 15 بزرگتر باشد یا اینکه point آنها از 15 کمتر باشد، با برقرار بودن هر کدام از این دو شرط فیلد متناظر انتخاب و به لیست نتایج اضافه می شود.

استفاده از IN و BETWEEN


آخرین دستوراتی که در این آموزش قصد بررسی آنها را داریم IN و BETWEEN هستند، IN وجود مقدار ستون مد نظر در لیست مقادیر یا نتیجه یک پرس و جوی مستقل زیرمجموعه (Subquery) دیگر را بررسی می کند، BETWEEN نیز برای بررسی قرار داشتن مقدار ستون مورد نظر در یک بازه (Range) خاص (شامل اعداد و تاریخ) استفاده می شود.
به فرض اگر بخواهیم از نمونه جداولی که در بالا ایجاد کرده ایم صرفا ردیف هایی از جدول tbl_1_name استخراج شوند که مقادیر ستون name آنها در جدول tbl_2_name وجود داشته باشد می توانیم پرس و جوی متغیر sql را به شکل زیر بنویسیم:
SELECT name, age, point FROM tbl_1_name WHERE name IN (SELECT name FROM tbl_2_name)
خروجی نمونه پرس و جوی بالا به شکل زیر خواهد بود:
Row Count: 2
Row 1 => Name: A - Age: 20 - Point: 12
Row 2 => Name: C - Age: 15 - Point: 33
از دستور IN برای جستجو در لیست مقادیر هم می توانیم استفاده کنیم، مثال:
SELECT name, age, point FROM tbl_1_name WHERE name IN ('A', 'D', 'F')
خروجی این حالت به شکل زیر خواهد بود:
Row Count: 3
Row 1 => Name: A - Age: 20 - Point: 12
Row 2 => Name: D - Age: 23 - Point: 12
Row 3 => Name: F - Age: 16 - Point: 35
دستور IN در حالت لیست معادل کاربرد چند OR در پرس و جو است.
شکل منفی دستور IN با افزودن NOT قابل تعریف است، در این حالت ردیف هایی انتخاب می شوند که در لیست IN وجود نداشته باشند، مثال:
SELECT name, age, point FROM tbl_1_name WHERE name NOT IN (SELECT name FROM tbl_2_name)
خروجی این پرس و جو به شکل زیر خواهد بود:
Row Count: 4
Row 1 => Name: B - Age: 13 - Point: 15
Row 2 => Name: D - Age: 23 - Point: 12
Row 3 => Name: E - Age: 12 - Point: 13
Row 4 => Name: F - Age: 16 - Point: 35
همان طور که مشخص است ردیف هایی از جدول tbl_1_name استخراج شده اند که مقادیر ستون name آنها در جدول tbl_2_name وجود ندارد.
دستور BETWEEN نیز برای محدود کردن نتایج مورد نظر به بازه خاصی کاربرد دارد، این بازه با توجه به نوع داده ستون مورد نظر می تواند عدد یا تاریخ باشد، به فرض اگر بخواهیم از جدول tbl_1_name صرفا ردیف هایی را استخراج کنیم که مقادیر point آنها بین 13 و 33 باشد قسمت sql را به شکل زیر می نویسیم:
SELECT name, age, point FROM tbl_1_name WHERE point BETWEEN 13 AND 33
خروجی پرس و جوی بالا به شکل زیر خواهد بود:
Row Count: 3
Row 1 => Name: B - Age: 13 - Point: 15
Row 2 => Name: C - Age: 15 - Point: 33
Row 3 => Name: E - Age: 12 - Point: 13
در حالت مثبت BETWEEN اعداد 13 و 33 راهم شامل می شود (در اصطلاح Inclusive) و معادل بزرگتر مساوی و کوچکتر مساوی (<= و >=) است، اما در حالت منفی با NOT اعداد 13 و 33 شامل نمی شوند، مثال:
SELECT name, age, point FROM tbl_1_name WHERE point NOT BETWEEN 13 AND 33
که خروجی این پرس و جو برابر است با:
Row Count: 3
Row 1 => Name: A - Age: 20 - Point: 12
Row 2 => Name: D - Age: 23 - Point: 10
Row 3 => Name: F - Age: 16 - Point: 35
مقایسه BETWEEN در حالت منفی بر مبنای بزرگتر و کوچکتر (< و >) است.
دستور BETWEEN برای استخراج نتایج در بازه زمانی نیز کاربرد دارد، در این حالت به جای دو عدد دو تاریخ با فرمت میلادی (yyyy-mm-dd) یا به صورت برچسب زمان (Unix Timestamp) به عنوان نقطه شروع و پایان بازه جستجو در جدول در نظر می گیریم، مثال:
SELECT col_name FROM tbl_name WHERE col_date BETWEEN '2020-01-02' AND '2020-03-18';
در حالت عادی رفتار BETWEEN به صورت Inclusive است یعنی خود تاریخ شروع و پایان را نیز شامل می شود اما اگر تاریخ ها به همراه زمان یا با نوع داده نامعتبری باشند ممکن است برخی ردیف ها در لیست نتایج انتخاب نشوند، برای دریافت تمام ردیف ها شامل روز شروع و پایان و جلوگیری از مشکلات پیش بینی نشده می توانیم با تابع DATE یا CAST به صورت نمونه های زیر ورودی ها یا مقدار ستون مورد نظر را به فرمت استاندارد تبدیل کنیم:
SELECT col_name FROM tbl_name WHERE col_date BETWEEN CAST('2014-02-01 21:13:16' AS DATE) AND CAST('2014-02-28 06:11:01' AS DATE);

SELECT col_name FROM tbl_name WHERE DATE(col_date) BETWEEN '2014-02-01' AND '2014-02-28';
در صورت کار با تاریخ و زمان به صورت برچسب زمان (Unix Timestamp) تابع UNIX_TIMESTAMP برای تبدیل تاریخ عادی به برچسب زمان و تابع FROM_UNIXTIME برای تبدیل برچسب زمان به تاریخ عادی در پرس و جوهای MySQL کاربرد خواهند داشت، مثال:
SELECT col_name FROM tbl_name WHERE col_date BETWEEN UNIX_TIMESTAMP('2014-02-01 00:00:00') AND UNIX_TIMESTAMP('2014-02-28 00:00:00');

SELECT col_name FROM tbl_name WHERE FROM_UNIXTIME(col_date) BETWEEN '2014-02-01 00:00:00' AND '2014-02-28 00:00:00';
دسته بندی: آموزش مقدماتی » MySQL
related مطالب بیشتر:
ساخت دیتابیس، جدول و ستون با دستور CREATE در MySQL
انتخاب ردیف ها با دستور SELECT در MySQL
توابع تجمیعی (Aggregate Functions) در MySQL
استفاده از JOIN و ساخت پرس و جوی ترکیبی در MySQL
آموزش MySQL، سیستم مدیریت پایگاه داده
دیدگاه
more ۳۵ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
شریفی
۰۷:۱۴ ۱۴۰۱/۰۳/۱۳
سلام. ممنونم لطف کردین.
شریفی
۱۳:۰۵ ۱۴۰۱/۰۳/۱۲
سلام و وقت بخیر.
من یه سوال در مورد سورت اطلاعات یه فروشگاه اینترنتی داشتم. فرض کنیم دو تا جدول داریم. در جدول 1 مشخصات کالا مثل عنوان و ... ذکر شده که حدود 10.000 قلم کالا داخلش هست.
مثلا :
A ...... مشخصات کالا
B ...... مشخصات کالا
C ...... مشخصات کالا
در جدول 2 قیمت کالا ها ذکر شده که ممکنه برای یه کالا بیشتر از 10 قیمت متفاوت وارد شده است و حدود 150.000 رکورد قیمتی داره.
مثلا :
A ..... 20.000
B ..... 40.000
A ..... 30.000
C ..... 50.000
B ..... 70.000
حالا چطور می تونیم اطلاعات رو به صورت زیر سورت کنیم:
کالا ها در جدول 1 به ترتیب میانگین قیمت در جدول 2 سورت بشن.
مثلا :
B ..... 55.000
C ..... 50.000
A ..... 25.000
هر چی گشتم توی اینترنت چیزی سر در نیاوردم. دنبال یه دستور بهینه می گردم. به همچین دستوری رسیدم:
Select `id`,`title`,`pic` From `tb1` Where find_in_set('XXX',cat) ORDER BY (SELECT AVG(price) AS price FROM `tb2` WHERE prdid = tb1.id and `stats` = '1' and `vojod` = '1') DESC Limit 100
نمیدونم کار می کنه یا نه.
آیا این درسته و میشه بهینه تر بشه؟ با توجه به اینکه تعداد رکوردها بالاست و در هر بار فراخوانی لیست محصولات باید این دستور اجرا بشه.
برای چینش (Sort) نتایج جدول اول بر اساس میانگین قیمت از جدول دوم می توانید از نمونه کد زیر الگوبرداری کنید:
SELECT t1.stuff, AVG(t2.price) AS avg_price FROM tbl_1 t1 JOIN tbl_2 t2 ON t1.stuff = t2.stuff GROUP BY t1.stuff ORDER BY avg_price DESC 
در این نمونه پرس و جو tbl_1 و tbl_2 جداول، نام ستون کالا stuff و نام ستون قیمت price است، حرف t مخفف جدول و شماره 1 و 2 شماره جدول مربوطه است، عبارت avg_price یک ستون فرضی است که میانگین قیمت ها را برای هر کالا در خود نگهداری می کند و می توانیم در حلقه while از آن برای گرفتن خروجی استفاده کنیم، نمونه نتایج نهایی:
stuf   avg_price
B 3166
A 1500
C 1125
این روش به شرط رعایت سایر اصول طراحی ساختار دیتابیس به فرض استفاده از سیستم ایندکس گذاری (Indexing)، بهینه است.
مجید
۱۲:۴۹ ۱۴۰۰/۱۲/۱۳
سلام خسته نباشید
ببخشید من کدی میخواستم که مقدار price رو از پروداکت بگیره و از کوچک ترینش به ترتیب تا بزرگترش نشون بده
لطفا آموزش را مطالعه کنید، با دستور ORDER BY می توانید مرتب سازی صعودی را داشته باشیم، به فرض:
SELECT price FROM product WHERE id > 0 ORDER BY price ASC LIMIT 50
قاعدتا ابتدا باید اتصال با دیتابیس برقرار شود، اگر آموزش را از ابتدا مطالعه کنید می توانید کد کامل پرس و جو را بنویسید.
م
۱۳:۵۵ ۱۴۰۰/۱۱/۱۰
توی سوال قبلی فراموش کردم بنویسم.
در ادامه سوال : امکان سورت کردن بر اساس فراوانی وجود داره؟
مثلا:
10-رضا-علی-حسین (3کاربر)
2-رضا-علی (2کاربر)
6-علی- محمد (2کاربر)
4-حسین (1کاربر)
5-علی(1کاربر)
در این مورد ارتباط منطقی برای بدست آوردن نتایج پیدا نمی کنیم، به طور مثال در ردیف اول وجود کاربر حسین در کنار دو کاربر دیگر چه رابطه منطقی دارد؟ مقدار آنها هم مشترک نیست.
م
۱۳:۴۸ ۱۴۰۰/۱۱/۱۰
سلام استاد عزیز
یه سوال در مورد دستور SQL جدولی به صورت زیر داشتم.
شماره - کاربر
2-علی
3-رضا
2-رضا
4-حسین
5-علی
6-محمد
6-علی
حالا توی SQL باید چه دستوری بنویسیم که اطلاعات به صورت زیر نمایش داده بشه:
2-علی و رضا
3-رضا
4-حسین
5-علی
6-محمد و علی
در واقع نام کاربرانی که شماره تکراری دارن نمایش داده بشه و مابقی هم به صورت عادی نمایش بدیم.
ممنونم.
برای ترکیب مقادیر ردیف های دیتابیس و گروه بندی همزمان می توانیم از پرس و جوی نمونه زیر در MySQL الگوبرداری کنیم:
SELECT GROUP_CONCAT(`user`), `number` FROM tbl GROUP BY `number` ORDER BY `number` ASC
در اینجا ستون user نام کاربر و ستون number شماره متناظر است.
سینا
۰۱:۱۶ ۱۴۰۰/۰۷/۰۴
سلام من میخوام در پی اچ پی اخرین id جدول sql را باز خوانی کنم یعنی اطلاعات بالا ترین id را برایم نشان بده و از ان اطلاعات فقط یک قسمت را بردارم ؟؟؟؟؟؟ لطفا سریع جواب بدی با تشکر از اموزش عالیتون
با ORDER BY، DESC و LIMIT می توانید این پرس و جو را اجرا کنید، به فرض:
SELECT name, age, point FROM tbl_1_name WHERE name != '' ORDER BY id DESC LIMIT 1
برای استخراج مقادیر و گرفتن خروجی از نمونه کدهای این آموزش در حلقه while می توانید الگوبرداری کنید.
ایمان
۱۸:۲۲ ۱۴۰۰/۰۶/۲۰
سلام وقت بخیر
من می خوام در یک بازه زمانی اطلاعات رو نشون بدم کد من به اینصورت هست:
<?php
$a=$_POST['timesabt'];
$b=$_POST['timesabt'];
if(count($_POST)>0) { $result = mysqli_query($con,"SELECT * FROM tbldata WHERE timesabt BETWEEN '$a' AND '$b'"); }
$i=0;
echo "<table><thead><tr><th>time </th></tr></thead><tbody>";
while($row = mysqli_fetch_array($result)) { ?>
<tr><td><?php echo $row['timesabt']?></td></tr>
<?php $i++; } ?>
<form method="post" action=""><input type="text" name="a" value=""> <input type="text" name="b"value=""><button type="submit" name="save"></button></form>
موقع اجرا پیغام های زیر رو میده:
1- PHP Warning:  mysqli_fetch_array() expects parameter 1 to be mysqli_result, bool given in
2- Undefined index: timesabt in search.php on line 22
ممنون میشم راهنمایی بفرمایید
خطای اول مربوط به وجود مشکل در برقراری ارتباط با MySQL یا یکی از پرس و جوها است، برای خطایابی می توانید از تابع mysqli_error که در این آموزش هم در کدها درج شده استفاده کنید، به فرض:
$result = mysqli_query($con,"SELECT * FROM tbldata WHERE timesabt BETWEEN '$a' AND '$b'");
if(!$result) {
echo mysqli_error($con);
}
خطای Undefined index احتمالا به این علت است که اطلاعات متغیرها از فرم HTML دریافت می شود اما فرم هنوز ارسال نشده است و Index مربوطه در آرایه POST وجود ندارد، برای عدم نمایش این خطا می توانید علامت @ را در ابتدای متغیر درج کنید:
@$a=$_POST['timesabt'];
@$b=$_POST['timesabt'];
جواد عباسی
۰۷:۳۳ ۱۳۹۹/۰۹/۱۰
سلام علیکم، از سایت بسیار خوب تون ممنونم، ما یه سایتی قبلا داشتیم و از پایتون و دیتابیس پستگرس استفاده میکردیم که حدود هزار کاربر با اطلاعات ثبت شده توش داریم، الان سایت رو با وردپرس به روز کردیم، سوالم این هست که چه جوری میشه اون اطلاعات هزار کاربر رو به دیتابیس پیش فرض وردپرس که مای اس کیو ال هست انتقال داد، خیلی نیاز به جواب دارم اگه راهی هست ممنون میشم راهنمایی کنید.
به نظر ابتدا باید دیتابیس را به همان صورت به MySQL تبدیل کنید که چند گزینه برای این کار در دسترس است (تست نشده)، از جمله:
https://dev.mysql.com/downloads/workbench/
آموزش:
https://mysqlworkbench.org/2012/11/how-to-migrate-postgresql-databases-to-mysql-using-the-mysql-workbench-migration-wizard/
و همچنین به صورت آنلاین:
http://www.lightbox.ca/pg2mysql.php
سپس باید متناسب با فیلدهای مبداء و فیلدهای مد نظر مقصد در وردپرس اسکریپتی با PHP بنویسید که اطلاعات را از دیتابیس قدیم به جدید و در ستون های مد نظر منتقل کند.
مبین
۰۹:۵۸ ۱۳۹۹/۰۸/۰۹
با سلام من می خواستم دستوری در دیتابیس بنویسم که بر اساس قد افراد نتایج را مرتب و چاپ کند و اگه قد برار بود آن کسی که وزنش کمتر است را چاپ کند میشه سینتکس این را به من بگین
با تشکر
برای حذف موارد تکراری ستون قد و انتخاب بزرگترین مقدار بر اساس ستون وزن می توانید دستور MIN MAX را با GROUP BY مطابق نمونه پرس و جوی زیر ترکیب کنید:
SELECT id, name, col_length, MIN(col_weight) FROM tbl WHERE id > 0 GROUP BY col_length ORDER BY id ASC LIMIT 30
نام و تعداد ستون ها را مطابق ساختار دیتابیس خود ویرایش کنید.
۱۲:۱۵ ۱۳۹۹/۰۷/۱۵
سلام واقعا من خیلی گشتم تا بتونم این آموزش رو پیدا کنم چون واقعا نمی دونستم چی بنویسم تا یک رتبه بندی برای نتایج جستجو پیدا کنم. هر جا رفتم مثل این سایت مفید نبوده واقعا توی کامل بودن آموزش ها و نحوه آموزش رتبه اول رو دارید. واقعا ممنون از این آموزش های کاملتون.
نظر لطف شما است.
نکته: آموزش بر مبنای اکستنش قدیمی MySQL است و به زودی به MySQLi ارتقاء داده می شود، لطفا توجه کنید در برنامه های جدید از MySQLi استفاده نمائید.
نبی
۰۰:۰۴ ۱۳۹۹/۰۷/۰۴
‏asc و desc رو جابجا نوشتی
خیلی ممنون از نکته سنجی، اصلاح شد.
امین
۱۳:۴۶ ۱۳۹۹/۰۲/۲۸
خیلی خیلی ممنون از اینکه جواب دادید
اما الان که امتحان کردم مجموع همه ی سفارشات رو میزنه یعنی اگر 3 نفر سفارش دادن میزنه 3 (یعنی تعداد ایدی ها رو میشماره)
سوال دومم اینه که میخوام برای مثال بزنه
ایدی فروشنده
تعداد سفارش های اون ایدی
و تاریخ (تاریخ سفارش هر مشتری داخل همون تیبل sales موجوده)
اسم تیبل sales
ردیف هامم
datetime/agent_id/sale_id
اولین سایتی هستید که به موقع جواب میدید خیلی ممنونم از لطفتون
پرس و جوی قبلی با این فرض است که هر کاربر یک agent_id یکتا دارد که می تواند به هر تعداد سفارش با sale_id های متفاوت داشته باشد، در این ساختار نمونه پرس و جویی که در یادداشت قبل درج کردیم کاربرد دارد که باید مطابق با جدول و خروجی مورد نظر ویرایش کنید، در مورد بخش دوم سوال لطفا یک نمونه دیتابیس به صورت sql خروجی بگیرید (با برنامه phpMyAdmin) و به همراه یک اسکرین شات از نتیجه مد نظرتان (می توانید در فتوشاپ نمونه نتیجه مد نظرتان را به شکل تصویر گرافیکی طراحی کنید) به آدرس ایمیل ما (موجود در بخش تماس) ارسال نمائید و پاسخ را از همان طریق پیگیر باشید.
امین
۰۱:۰۰ ۱۳۹۹/۰۲/۲۸
درود به شما خسته نباشید
یک سوال داشتم خیلی گشتم اما پیدا نکردم
من دیتابیسی برای مثال invert دارم میخوام یک صفحه درست کنم که تاپ ها رو نشون بده یعنی داخل تیبل sale اطلاعات فروش هر کاربر هست (البته بصورت تک تک) اطلاعات داخل تیبل sale شامل sale_id و agent_id ووو هستش میخوام داخل یک لیست مشخص بشه فلان ایدی چند تا سفارش داشته و بالای لیست قرار بگیره (البته هر سفارش جدا جدا ثبت شده)
یعنی میخوام بشماره که فلان ایدی چند سفارش ثبت کرده و بالای لیست قرار بگیره
امیدوارم کامل توضیح داده باشم
با فرض اینکه آی دی هر مشتری در ستون agent_id باشد می توانید با COUNT، GROUP BY و ORDER BY این کار را مشابه نمونه زیر انجام دهید:
SELECT `agent_id`, COUNT(`agent_id`) AS count_sale FROM `sale` GROUP BY `agent_id` ORDER BY count_sale DESC LIMIT 10
این پرس و جو 10 ردیف دارای بیشترین فروش را به ترتیب از بیشتر به کمتر انتخاب می کند، قاعدتا برای گرفتن خروجی HTML باید از اکستنش MySQLi یا PDO و کدنویسی PHP مطابق با ساختار برنامه خودتان استفاده کنید، برای تست می توانید در برنامه phpMyAdmin نمونه جدول طراحی و در قسمت SQL پرس و جو را امتحان کنید.
Shahram
۱۳:۳۲ ۱۳۹۸/۰۷/۱۵
با سلام
بعد از اجرای دستورات با group by خطای only full group by برگشت داده میشود. علت چیه؟
ظاهرا MySQL از نسخه 5.7.5 به صورت پیش فرض ONLY_FULL_GROUP_BY را در SQL Mode فعال کرده است و این یعنی در پرس و جویی که اجرا می کنیم باید دقیقا مشخص کنیم چه ردیف هایی برای گروه بندی مد نظر هستند، نمونه پرس و جوی شما مشخص نیست اما به طور کلی چند راه حل برای رفع این مشکل وجود دارد:
- افزودن ستون در قسمت GROUP BY به فرض:
از
SELECT name, family FROM tbl GROUP BY name;
به
SELECT name, family FROM tbl GROUP BY name, family;
یا به
SELECT id, name, family FROM tbl WHERE family != '' GROUP BY id, name;
- استفاده از تابع ANY_VALUE برای ستون مشخص نشده در قسمت GROUP BY، به فرض:
SELECT name, ANY_VALUE(family) FROM tbl GROUP BY name;
- در صورت دسترسی به تنظیمات MySQL می توانیم ONLY_FULL_GROUP_BY را از SQL Mode حذف کنیم (این روش توصیه نمی شود!)، برای این کار در برنامه PHPMyAdmin در قسمت SQL پرس و جوی زیر را اجرا می کنیم:
SET sql_mode=(SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));
نکته: راه حل های بالا باید با دقت و پس از تست و بررسی کافی اعمال شوند تا باعث دریافت نتایج ناخواسته نشوند!
محمد جواد
۰۱:۲۶ ۱۳۹۸/۰۴/۰۶
سلام
یک راهنمایی برای نوشتن این پرسش از شما دارم
در mysql سطرای دو جدول مشابه رو با هم مقایسه کنه و سطرای دارای اختلاف رو در خروجی نمایش بده
سپاس
با یکی از نمونه پرس و جوهای زیر می توانید سطرهای دارای اختلاف بین دو جدول مشابه را در خروجی نمایش دهید:
SELECT * FROM tbl_1
WHERE col_1 NOT IN (SELECT col_2 FROM tbl_2)
UNION
SELECT * FROM tbl_2
WHERE col_2 NOT IN (SELECT col_1 FROM tbl_1)

SELECT id, col
FROM (SELECT tbl_1.id, tbl_1.col FROM tbl_1
UNION ALL
SELECT tbl_2.id, tbl_2.col FROM tbl_2) AS t
WHERE id IN (SELECT id FROM tbl_1) AND id IN (SELECT id FROM tbl_2)
GROUP BY id, col
HAVING COUNT(*) = 1
ORDER BY id
در این نمونه پرس و جوها به جای tbl نام جدول و به جای col نام ستون های مشابه را باید جایگزین کنید.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
5 × 3
20 × 20
=