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

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 مطالب بیشتر:
استفاده از WHERE در پرس و جوی MySQL
آموزش MySQL، سیستم مدیریت پایگاه داده
اتصال PHP به MySQL با اکستنشن MySQLi
نحوه ذخیره کردن اطلاعات با دستور INSERT در MySQL
توابع تجمیعی (Aggregate Functions) در MySQL
دیدگاه
more ۳۵ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
امیرحسین
۰۱:۱۰ ۱۳۹۸/۰۲/۲۷
سلام مجدد لطفا کد زیر را در این مطلب ویرایش کنید
mysql_query("SELECT * FROM table WHERE name != '' AND age > 40 OR name != '' AND age < 20 ORDER BY age");
این کد را میتوان به این شکل ساده تر نمود
mysql_query("SELECT * FROM table WHERE name != '' AND (age > 40 OR age < 20) ORDER BY age");
استفاده از پرانتز کلید تکرار نشدن کدها است. احتمالا استاد نمیدونستن با عرض پوزش
سپاس فراوان از نکته سنجی و تذکر بجا، آموزش ها قدیمی و در حال به روزرسانی هستند، مطلب ویرایش و اصلاح شد.
اکبر
۱۲:۴۸ ۱۳۹۷/۱۱/۱۱
خیلی ممنون این کد تو مرورگر نمایش میده من میخوام عدد رتبه کاربر رو به برنامه ارسال کنم تا کاربر ببینه کدوم متغیر را باید ارسال کنم ایدی رو از جدول دریافت کنم و ارسال یا چی رو ممنون بعد من کدایی که نوشتم نحوه ارسالشان فرق میکنه اگه زحمتی نیست اون خط کد ارسالش رو هم بنویسید میدونم دو سه تا کلمست ولی من هر چی نوشتم نشد ممنون
این موارد را باید در آموزش های مقدماتی MySQL فرا بگیرید، صرفا جهت راهنمایی بیشتر با توجه به پرس و جو در قسمت گرفتن خروجی در کدهای PHP از ستون فرضی position مقدار رتبه کاربر را دریافت می کنیم، مثال:
$sql = "SELECT `id`, `user`, (SELECT COUNT(*) FROM `table` WHERE table.point >= (SELECT `point` FROM `table` WHERE `user` = 'D')) AS `position` FROM `table` WHERE `user` = 'D'";
$result = mysqli_query($conn, $sql);
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)){
echo $row["position"];
}
قاعدتا این کد کامل نیست و با توجه به اکستنشی که از آن استفاده می کنید (MySQL، MySQLi یا PDO) باید قسمت ارتباط با پایگاه داده را اضافه و نام کاربر را ویرایش کنید، یعنی به جای عبارت D که فرضی است نام کاربر را به صورت متغیر در پرس و جو جایگزین نمائید، با توجه به اینکه یکی از ساده ترین روش های هک سایت ها نفوذ از طریق پرس و جوهای دیتابیس است، اکیدا توصیه می کنیم آموزش های مقدماتی MySQL را از پایه دنبال کنید تا با نحوه نوشتن پرس و جوهای امن و استفاده از روش هایی مانند Prepared Statements آشنا شوید.
اکبر
۱۱:۵۹ ۱۳۹۷/۱۱/۰۷
با سلام خدمت استاد عزیز
من یه جدول ساختم که توش چندین کاربر با امتیازات متفاوت وجود داره و این امتیازات هر لحظه متغیر است میخوام هر دفعه کاربر درخواست داد بتونه با توجه به امتیاز خود رتبه خودش رو ببینه یعنی جدول بر ارسال امتیاز نفرات را مرتب کنه و کسی که درخواست کرده در ردیف چند هست را براش بفرسته مثال ساده اینکه مثلا سه نفر تو جدول هستش
اکبر 10 امتیاز
علی 7 امتیاز
نادر 5 امتیاز
حالا وقتی علی خواست رتبه رو ببینه جدول بر ارسال امتیاز اول بیاد اوردر بای کنه تا اسامی طبق چینش بالا مرتب بشه و بعد علی که در رتبه دوم هست عدد 2 را براش ارسال کنه ممنون میشم این کد رو برام بفرستین مرسی
می توانید از نمونه پرس و جوی زیر استفاده کنید (تست شده):
SELECT `id`, `user`, (SELECT COUNT(*) FROM `table` WHERE table.point >= (SELECT `point` FROM `table` WHERE `user` = 'D')) AS `position` FROM `table` WHERE `user` = 'D'
برای تست پرس و جوی بالا یک جدول با نام فرضی table با سه ستون id، user و point در برنامه phpMyAdmin بسازید و چند کاربر با نام های A، B، C و D را با مقادیر دلخواه وارد کنید.
امیرحسین
۱۹:۴۸ ۱۳۹۷/۰۸/۱۷
سلام استاد گرانقدر نهایت خسته نباشید و کمال تشکر رو دارم از شما و همچنین عمر طولانی، سلامت و شادی آرزو دارم برای شما
دوتا سوال دارم
سوال اول در مورد group by
SELECT `tbl_packages`.`id`, COUNT(`tbl_stickers`.`id`) AS `total_stickers` FROM `tbl_packages` INNER JOIN `tbl_stickers` ON `tbl_packages`.`id` = `tbl_stickers`.`package_id` GROUP BY `tbl_stickers`.`package_id` HAVING `total_stickers` < '3'
من اینجا میخوام در خروجی فقط ستون id از جدول tbl_packages بره و چیز دیگه ای نره الان هم آیدی به خروجی میره هم total_stickers به نظر شما چه راهی دارم ؟ اگه این دستور رو بردارم
COUNT(`tbl_stickers`.`id`) AS `total_stickers`
مشکل تا حدی حله ولی عملیات group by بهم میریزه و از ستون فرضی که ساختم قسمت شرط HAVING ازش استفاده میکنم لطفا یه راه حلی بدید
اما سوال دوم در مورد بازم GROUP BY
من یک هاستی خریدم که عملیات گروپ بای مشکل داره در بعضی موارد مثلا اگه دستور بالا رو بنویسم مشکل نداره اما همون دستور بالا رو اگه اینطوری تغییر بدم مشکل داره
SELECT * FROM `tbl_packages` INNER JOIN `tbl_stickers` ON `tbl_packages`.`id` = `tbl_stickers`.`package_id` GROUP BY `tbl_stickers`.`package_id`
اما اگه select * from رو یه تغییری بدم مثلا اینطوری کنم
select `tbl_packages`.* FROM
مشکلش رفع میشه یا اینکه اگه این دستور رو بنویسم مشکل داره
SELECT * FROM `tbl_users` GROUP BY `chat_id`
در اینجا اگه * (استار) رو تغییر بدم مثل قبلی بازم مشکلش رفع نیمشه و در هر دو مورد یک ارور رو میدن که متن ارور رو عکسشو لینکش در پایین هست
http://up.iranblog.com/files/1541788655.png
توضیحات اضافی:
در مورد این مشکل با پشتیبانی هاستم صحبت کردم گفت با یک برنامه نویس در این مورد صحبت کنید احتمالا کدای mysql بلد نیستید!! ولی همین کارا رو تو xampp انجام میدم هیچ مشکلی نداره
سپاس فراوان از نظر لطف و محبت شما.
در مورد سوال اول می توانید پرس و جو را به شکل زیر ویرایش کنید:
SELECT `tbl_packages`.`id` FROM `tbl_packages` INNER JOIN `tbl_stickers` ON `tbl_packages`.`id` = `tbl_stickers`.`package_id` GROUP BY `tbl_stickers`.`package_id` HAVING COUNT(`tbl_stickers`.`id`) < '3';
در مورد سوال دوم این به فعال بودن حالت ONLY_FULL_GROUP_BY در SQL Mode برمی گردد، ظاهرا در آخرین نسخه های MySQL این حالت به صورت پیش فرض فعال است و بهتر است پرس و جوها را با همین فرض بنویسید، در صورت نیاز نیز می توانید از طریق برنامه phpMyAdmin سربرگ Variables قسمت sql mode را پیدا کرده و پارامتر ONLY_FULL_GROUP_BY را حذف کنید، اگر دسترسی به این قسمت محدود شده باشد باید از پشتیبانی هاست خود بخواهید.
اکبر
۱۹:۲۰ ۱۳۹۷/۰۵/۲۱
با تشکر به خاطر راهنمایی که کردید ولي متاسفانه من نتونستم نتیجه را تغییر دهم اگر امکانش هست میتوانید کل کد را با همین روشی که گفتیم بنویسید یعنی کل اون کپی که براتون فرستادم را ویرایش کنید و کلش را بنویسید
بازم از زحماتتون ممنونم
به دلیل زمانبر بودن حل مشکل مطرح شده، متاسفانه چنین امکانی مقدور نیست، لطفا به یک برنامه نویس وب مراجعه فرمائید.
اکبر
۲۱:۵۵ ۱۳۹۷/۰۵/۲۰
با سلام مجدد دوست عزیز اون قسمتی که شما ویرایش کردید نیازی به ویرایش نداره چون درست کار میکنه مشکل اینجاست که نیم هر پنج اسم از جدول را می فرسته اما میخوام یک اسم بفرسته با یه مشخصه که تو برنامه اسم یک را تو یه تکست و اسم دو را تو یه تکست دیگه نشون بدم این همه پنج اسم رو باهم می فرسته و نمیشه جدا سازی کرد نمیدونم منظورم رو گرفتین یا نه به طور خلاصه چطور میتونم برای خروجی ليميت پنج متغیر بسازم که متغیر اول نام ليميت یک را ارسال کنه متغیر دوم نام ليميت دوم را و الی آخر نمیدونم متوجه شدید منظورم رو یا نه
همان طور که گفتیم به کدهای شما دسترسی نداریم تا ببینیم خروجی نهایی به چه نحوی تجزیه و چاپ می شود، در کل با قرار دادن تمام آیتم ها در یک آرایه می توان آنها را مورد به مورد تجزیه کرد، کد فعلی شما خروجی به شکل نمونه زیر ایجاد می کند:
Array
(
[0] => Array
(
[Name1] => 1
[Score1] => 1
)
)
بر همین اساس راه حل پیشنهادی ایجاد خروجی به صورت نمونه آرایه زیر بود (کد ویرایش شده خروجی مشابه این آرایه تولید می کند):
Array
(
[0] => Array
(
[Name1] => 1
[Score1] => 1
)
[1] => Array
(
[Name2] => 2
[Score2] => 2
)
[2] => Array
(
[Name3] => 3
[Score3] => 3
)
[3] => Array
(
[Name4] => 4
[Score4] => 4
)
)
اگر با آرایه ها در PHP آشنا باشید می توانید از این خروجی هر طور که مورد نیاز است استفاده کنید، البته احتمالا باید کدهای قسمت چاپ نتیجه نیز ویرایش شوند، اگر نتوانید از این آرایه استفاده کنید صرفا با دسترسی و امکان تست کدها است که می توان مشکل را رفع کرد.
اکبر
۰۰:۱۲ ۱۳۹۷/۰۵/۲۰
$pdo = new PDO(dsn, username, password);
if(isset($_POST['Rotbe'])){
$stmt = $pdo -> query( ' SELECT * FROM Emtiyazat ORDER BY Score DESC LIMIT 10 ');

$a = array ();
$loop = 1;

while($row = $stmt->fetch ()){
array_push($a, array('Name' . $loop => $row['Name'], 'Score' . $loop => $row['Score']));
$loop++;
}

echo json_encode($a);
$pdo = null;
}
با سلام خدمت استاد عزیز
کد بالا درست کار میکنه و طبق دستور نام و امتیازات ده نفر اول جدول بر اساس id را ارسال میکنه و در برنامه در یک تکست نشان میدهد مشکل همین است تمام اسمها را در یک تکست نشان میدهد من اگر بخواهم نام نفر اول را و دوم را و سوم را و تا ده هر کدام را جدا جدا بفرستت باید چه دستوری اضافه کنم
در اینجا Name1 تمامی اسمها را دریافت میکند مثلا چه دستوری بنویسم که Name1 نام نفر اول جدول طبق id بگیرد و مثلا Name2 نام نفر دوم و الی اخر
ممنون از سایت خوبتون
با توجه به توضیحات برنامه شما در این بخش شامل دو قسمت می شود، قسمت اول وظیفه ایجاد خروجی اولیه را دارد که کد آن را درج کرده اید و مطابق با نیازتان آن را ویرایش کرده ایم، اما قسمت دوم نحوه استفاده از این خروجی اولیه جهت ایجاد نتیجه نهایی برای سمت کاربر است که کدهای این قسمت برایمان مشخص نیست و قاعدتا ممکن است متناسب با تغییرات اعمال شده به درستی کارایی نداشته باشد و قاعدتا باید این قسمت نیز ویرایش شود.
نیما
۰۰:۵۰ ۱۳۹۴/۱۰/۲۴
با سلام چرا وقتی از rand دقیقا مثل آموزش شما استفاده میکتم به من اخطار syntax میده
دقیقا این
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'rand()' at line 1
در این قسمت یک اشکال جزئی وجود داشت که با یادآوری شما اصلاح شد!، از نمونه کد فعلی استفاده کنید.
کارجو
۱۷:۳۰ ۱۳۹۴/۰۶/۱۱
ممنون. خیلی مفید بود.
علی احمدی
۱۴:۱۷ ۱۳۹۴/۰۱/۱۰
با سلامی دوباره
مشکل اینجا بود که id از نوع int نبود. حل شد. خیلی خیلی ممنون از لطف شما
علی احمدی
۱۱:۲۱ ۱۳۹۳/۱۲/۲۶
سلام دوباره
بدون شرط هم امتحان کردم ولی باز مرتب نمیکنه طرز صحیح نوشتن کد با شرط و بدون شرط رو اگه ممکنه بهم بگین. ممنون
res = mysqli_query($conn, "select * from sabt  Order By id");
به نظر مشکل دیگری در برنامه یا دیتابیس شما وجود دارد، اگر ID به صورت INT باشد و مقادیر آن متفاوت، اصولا باید چینش در یکی از حالت های آموزش داده شده صورت گیرد.
علی احمدی
۱۴:۱۹ ۱۳۹۳/۱۲/۲۵
سلام
این دستور رو نوشتم ولی زمانی که داده ها نمایش داده میشوند باز مرتب نشون نمیده
$res = mysqli_query($conn, "select * from sabt where id=$id Order By id");
در پرس و جو از علامت = استفاده شده و این یعنی تنها یک مقدار مورد نظر است (در این حالت تنها یک ID یا ID های مشابه انتخاب می شوند)، که چینش در چنین حالتی ممکن نیست!
مهران
۱۶:۴۴ ۱۳۹۳/۰۲/۲۱
سلام خسته نباشید.
من با دستور LIMIT تعداد رکورد های دریافتی رو 10 قرار دادم. حالا سوال اینه اگر قصد دسترسی به 10 رکورد بعدی رو داشته باشم باید چیکار کنم؟؟ و به همین ترتیب..
ممنون میشم راهنماییم کنید.
لطفا مطلب را با دقت مطالعه کنید، دستور LIMIT دو پارامتر دارد، در صورتی که هر دو پارامتر تنظیم شود، عدد اول نقطه شروع انتخاب ردیف ها و عدد دوم تعداد آنها است، برای کسب اطلاعات بیشتر، عبارت "صفحه بندی" را در قسمت جستجوی سایت وارد کنید.
علی امینی
۱۳:۲۰ ۱۳۹۲/۰۸/۰۹
با سلام
واقعا دستتون درد نکنه.
الان که بیشتر دقت میکنم میبینم که تو آموزش شما بهترین هستید.
واقعا کارتون عالیه.
ایشالا همیشه موفق باشید
یا علی
۱۶:۰۶ ۱۳۹۲/۰۸/۰۶
دوست واستاد گرامي سلام من يه كد دارم ميخوام وقتي مثلا مطلب جديدي پست ميكنم بياد اول در كد زير بايد چه تغييري بدم لازم به ذكر است با پست هر مطلب اطلاعات جدول از قديمي به جديد نمايش داده ميشه ميخوام در واقع برعكس اين بشه يعني هر پستي كه ارسال ميكنم بياد اول جدول
حذف شد
چه تغييري بايد در كد بالا بدم؟؟؟
از شما ممنون !!! لازم به ذكره با كمك هاي شما تا حالا تونستم يك مديريت محتواي ساده راه اندازي كنم.
با تشكر اوس
هرچند پاسخ دقیق به سوال شما نیاز به بررسی آنلاین تغییرات در خروجی دارد، اما به نظر با استفاده از ORDER BY و ASC یا DESC می توانید این کار را انجام دهید:
$query_Recordset1 = "SELECT * FROM page_index ORDER BY id ASC";
نکته: ستون id می تواند در جدول شما نام دیگری داشه باشد (معمولا id شماره یکتای هر مطلب از کوچکتر به بزرگتر است).
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
7 × 2
20 × 20
=