如何以逗号分隔记录的所有组合

时间:2019-04-24 14:34:01

标签: mysql

我有一张表,其中包含5个字段。

// Variables
@import 'variables_env';
@import 'variables';

// External 
@import '~bootstrap/scss/bootstrap';
@import '~@fortawesome/fontawesome-pro/scss/fontawesome';
@import '~@fortawesome/fontawesome-pro/scss/light';
@import '~@fortawesome/fontawesome-pro/scss/regular';
@import '~@fortawesome/fontawesome-pro/scss/solid';
@import '~@fortawesome/fontawesome-pro/scss/brands';
@import '~slick-carousel/slick/slick.css';

// Base
@import 'base/global';
@import 'base/typography';
@import 'base/backgrounds';
@import 'base/text-colors';
@import 'base/shadows';
@import 'base/helpers';

// Components
@import 'components/promotion-bar';
@import 'components/buttons';
@import 'components/action-bar-mobile';
@import 'components/breadcrumbs';
@import 'components/cookies';
@import 'components/tables';
@import 'components/forms';
@import 'components/separators';
@import 'components/stars-rating';
@import 'components/lists';
@import 'components/input-selector-box';
@import 'components/vue-tabs';
@import 'components/product-box';
@import 'components/product-box-category';
@import 'components/slick-carousel';
@import 'components/selector-product-list';
@import 'components/section';
@import 'components/testimonial';
@import 'components/pickpoint-info';
@import 'components/product-filter';
@import 'components/thematic-products-row';
@import 'components/navbar-accounts';

// Vendors
@import 'vendors/jqueryfancybox3/jquery.fancybox';

// Layout
@import 'layout/main-header';
@import 'layout/horizontal-megamenu';
@import 'layout/mobile-sidebar-megamenu';
@import 'layout/main-footer';
@import 'layout/admin';


// Pages
@import 'pages/index';
@import 'pages/product-page';
@import 'pages/products-list';
@import 'pages/cart';
@import 'pages/docs';
@import 'pages/offers';
@import 'pages/faq';

,并且我想在“站点”列上搜索表,但是该字段值将有任何组合。例如2,3,1或3,1,2等,其结果应为上述示例中ID为1和2的结果。 我也需要精确长度的结果作为搜索值。如果用户输入3个逗号分隔的值,那么我想要包含3个逗号分隔但完全组合的结果。

我尝试了“ IN”和“ LIKE”子句,但不适用于所有组合和精确长度搜索

IN子句 从tbl_demo中选择*,其中按(1,2,3)顺序排列的站点按1 DESC;

LIKE子句 从tbl_demo中选择*,其中“%1,2,3%”之类的网站按1 DESC排序;

1 个答案:

答案 0 :(得分:2)

从数据库规范化的角度来看,显然在逗号分隔的列表中存储数字字符串是错误的。我看到其他人试图解决这个问题,就像“在数据库列中存储分隔列表真的那么糟糕吗?”一样。但这不是重复的,因为它拒绝OP的问题而不是回答它。

让我们讨论解决此问题的方法。

第一个选择是将其正确规范化。创建一个子表,并在显示的表中存储对id的引用,以及每行一个网站值。

| id | site |
|  1 |    1 |
|  1 |    2 |
|  1 |    3 |
|  2 |    1 |
|  2 |    2 |
...

然后,您可以按组进行计数,或者至少按排序顺序进行GROUP_CONCAT(),以便可以与您的条件进行比较。

SELECT id, GROUP_CONCAT(site ORDER BY site) AS sites
FROM MyTable GROUP BY id
HAVING sites = '1,2,3'

如果您不能更改数据的组织结构,则可以修复字符串以使数字始终按升序排列会很有帮助。但是您可能无法做到这一点(或不想尝试)。

另一种选择是一次使用某些人用来搜索逗号分隔的字符串的FIND_IN_SET()hack一次比较一个值。它不是用于此目的的,它是与MySQL的SET data type一起使用的功能,但它也适用于字符串,因此,那些用逗号分隔的数字字符串的人都可以使用它。

SELECT ...
FROM YourTable
WHERE FIND_IN_SET('1', sites)
  AND FIND_IN_SET('2', sites)
  AND FIND_IN_SET('3', sites)

您需要与要搜索的号码一样多的字词。但您还需要确保集合中不包含更多个数字。

  AND LENGTH(sites) - LENGTH(REPLACE(sites, ',', '')) + 1 = ?

在此表达式中,?是我们要查找的元素数:3。

这种类型的解决方案可能有效,但无法优化。它将始终进行表格扫描,因此表格越大,扫描速度就越慢。