MySQL如果不是null的顺序

时间:2016-03-09 08:37:39

标签: mysql

我正在为我的业务目录应用程序编写存储过程。浏览列表表单有一个选择菜单,允许用户按特定字段订购列表。如果sortField参数不为null,则应按sortOrder(asc或desc)参数指定的顺序按该列排序。如果指定了sortField参数,那么将始终使用它指定sortOrder字段。我收到的错误是"Check the syntax near IF sortField != NUL .... ELSE ORDER BY l.lis"

这是我的问题:

CREATE PROCEDURE `ListingsRetrieve` (
    IN listingId INT(15),
    IN categoryID INT(15), 
    IN regionId INT(15),
    IN memberId INT(15), 
    IN keywords VARCHAR(250), 
    IN filterDistance INT(3), 
    IN latitude DOUBLE, 
    IN longitude DOUBLE, 
    IN sortField VARCHAR(16), 
    IN sortOrder VARCHAR(16), 
    IN page INT(15), 
    IN perPage INT(3)
    )
BEGIN

   SELECT 
    l.listing_id AS id, l.member_id, l.category_id, l.banner_id, l.thumbnail_id, l.logo_id, l.title AS listing_title, l.description, l.address, l.city, l.zip, UNIX_TIMESTAMP(l.date_submitted) AS date_submitted, l.latitude, l.longitude,l.phone,l.website, l.phone, l.contact_email, l.facebook_url, l.twitter_url, l.slug AS listing_slug,
l.sunday_open, l.sunday_close, l.monday_open, l.monday_close, l.tuesday_open, l.tuesday_close, l.wednesday_open, l.wednesday_close, l.thursday_open, l.thursday_close, l.friday_open, l.friday_close, l.saturday_open, l.saturday_close,
    ( 6371 * acos( cos( radians(latitude) ) * cos( radians( l.latitude) ) * cos( radians( l.longitude ) - radians(longitude) ) + sin( radians(latitude) ) * sin( radians( l.latitude ) ) ) ) AS distance,
    c.category_id AS cat_id, c.slug AS cat_slug, c.icon AS cat_icon, 
    r.region_id AS region_id, r.title AS region_title, r.slug AS region_slug, (FLOOR((AVG(rev.score)) * 2) / 2) AS stars,
    (SELECT 
        AVG(FLOOR(AVG(rev.score) * 2) / 2)
    FROM 
        reviews AS r 
    INNER JOIN 
        listings AS l ON r.review_listing_id = l.listing_id
) as totalAvg,
((COUNT(rev.review_id) / (COUNT(rev.review_id)+5)) * (FLOOR((AVG(rev.score)) * 2) / 2) + (5 / (COUNT(rev.review_id)+5)) * AVG(rev.score)) AS rating,
b.attachment_id AS banner_id, b.file_path AS banner_path,
t.attachment_id AS thumbnail_id, t.file_path AS thumbnail_path,
lgo.attachment_id AS logo_id, lgo.file_path AS logo_path,
CONCAT_WS('/', r.slug, c.slug, l.slug, l.listing_id) AS listing_uri
FROM listings AS l 
LEFT JOIN categories AS c ON l.category_id = c.category_id
LEFT JOIN regions AS r ON l.region_id = r.region_id
LEFT JOIN reviews AS rev ON l.listing_id = rev.review_listing_id
LEFT JOIN attachments AS b ON l.banner_id = b.attachment_id
LEFT JOIN attachments AS t ON l.thumbnail_id = t.attachment_id
LEFT JOIN attachments AS lgo ON l.logo_id = lgo.attachment_id
WHERE (listingId IS NULL or l.listing_id = listingId) AND
      (categoryId IS NULL or l.category_id = categoryId) AND
      (regionId IS NULL or l.region_id = regionId) AND 
      (memberId IS NULL or l.member_id = memberId) AND
      (keywords IS NULL or MATCH(l.title,l.description,r.title,c.title) AGAINST(keywords) AND
      (filterDistance IS NULL OR distance = filterDistance)

IF sortField != NULL THEN 
    ORDER BY sortField sortOrder
ELSE
    ORDER BY l.listing_id DESC

IF listingId != NULL THEN 
    LIMIT 1;
ELSE 
    LIMIT (IF page > 1 THEN ((page - 1) * perPage) ELSE 0),perPage
END IF;      

END //

1 个答案:

答案 0 :(得分:0)

您不能以这种方式构建动态查询。

您可以将查询组成一个变量中的字符串,然后使用该字符串prepare a statement并执行它:

# Put the common part of the query in a string. Take care to not include 
# the variable names but use CONCAT() to join their *values* into the SQL syntax.
# Or, if possible, replace them with question marks (?) and pass
# them to EXECUTE as parameter values (see below or read the documentation)
SET @sql = 'SELECT l.listing_id AS id, ... OR distance = filterDistance)';

# Add the ORDER BY clause
IF sortField IS NOT NULL THEN 
    SET @sql = CONCAT(@sql, ' ORDER BY ', sortField, ' ', sortOrder);
ELSE
    SET @sql = CONCAT(@sql, ' ORDER BY l.listing_id DESC');
END IF;

# Add the LIMIT clause; it uses parameters
SET @sql = CONCAT(@sql, ' LIMIT ?, ?');

# Compute the values of parameters to use in the LIMIT clause
IF listingId IS NOT NULL THEN 
    SET @start = 1;
    SET @limit = 1;
ELSE
    # Make sure @start is not negative
    SET @start = MAX(0, (page - 1) * perPage);
    SET @limit = perPage;
END IF;

# Use @sql to prepare a statement
PREPARE stmt1 FROM @sql;

# Run the prepared statement with parameters
EXECUTE stmt1 USING @start, @limit;
# Can run the prepared statement again, with different parameters if needed
# ...
# Remove the prepared statement when it is not needed any more
DEALLOCATE PREPARE stmt1;