【问题标题】:Fetch all records from table A where id = somvalue in B plus records which don't have id in B从表 A 中获取所有记录,其中 id = B 中的 somvalue 加上 B 中没有 id 的记录
【发布时间】:2020-12-30 04:34:59
【问题描述】:

我有两个表:coupons 表和 coupon_city_map 表。

id coupon_code
1 OFFER20
2 OFFER10
3 OFFER50
4 OFFER40
5 OFFER90
coupon_Id city_id
1 2
2 3
3 4
4 2

我需要 city_id = 2 的 ID 为 1 4, and 5 的优惠券。

所以它应该获取city_id=2 的所有优惠券,即ID为1 and 4的优惠券

它还应该获取在coupon_city_map 中没有密钥的优惠券,即5

这是我尝试过的,但[Op.or] 中的查询不起作用,而是返回所有优惠券。

let coupons = await Coupon.findAll({
      where: {
        [Op.or]: [
          { '$CouponCities.city_id$': city_id },
          { '$CouponCities.coupon_id$': null },
        ],
        ...filters // other filter like is_active: true
      },
      include: {
        model: CouponCity,
        attributes: [],
      },
      attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount', 'discount_upto', 'description', 'display'],
    });

正在生成的查询

SELECT `Coupon`.`id`, 
       `Coupon`.`coupon_code`, 
       `Coupon`.`discount_per`, 
       `Coupon`.`flat_discount`, 
       `Coupon`.`discount_upto`, 
       `Coupon`.`description`, 
       `Coupon`.`display` 
FROM `coupons` AS `Coupon` 
LEFT OUTER JOIN `coupon_city_map` AS `CouponCities` ON `Coupon`.`id` = `CouponCities`.`coupon_id` 
WHERE (`Coupon`.`user_id` IS NULL OR `Coupon`.`user_id` = 1) 
  AND `Coupon`.`is_active` = true 
  AND `Coupon`.`is_external` = false 
  AND `Coupon`.`start_date` < '2020-12-30 10:33:20' 
  AND `Coupon`.`expiry_date` > '2020-12-30 10:33:20';

更新 我也在下面尝试过,但它仍然退回所有优惠券。

let coupons = await Coupon.findAll({
    // where: {
    //   ...filters,
    // },
    include: {
      model: CouponCity,
      required: false,
      where: {
        [Op.or]: [
          {
            zone_id: zoneId,
          }, {
            coupon_id: null,
          },
        ],
      },
      attributes: [],
    },
    attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount','discount_upto', 'description', 'display'],
 });

...它会生成以下查询。

SELECT `Coupon`.`id`, 
       `Coupon`.`coupon_code`, 
       `Coupon`.`discount_per`, 
       `Coupon`.`flat_discount`, 
       `Coupon`.`discount_upto`, 
       `Coupon`.`description`, 
       `Coupon`.`display` 
FROM   `coupons` AS `Coupon` 
       LEFT OUTER JOIN `coupon_city_map` AS `CouponCities` 
                    ON `Coupon`.`id` = `CouponCities`.`coupon_id` 
                       AND ( `CouponCities`.`zone_id` = 1 
                             AND `CouponCities`.`coupon_id` IS NULL ) 
WHERE  `Coupon`.`is_active` = true 
       AND `Coupon`.`is_external` = false; 

【问题讨论】:

标签: mysql node.js sequelize.js


【解决方案1】:

这对我有用,查询很乱,但它有效。我发布了所有代码,以便有兴趣的人更好地理解。

这里zone 是城市。

{
  const filters = {
    start_date: {
      [Op.lt]: new Date(),
    },
    expiry_date: {
      [Op.gt]: new Date(),
    },
  };
  if (userId) {
    filters[Op.or] = [{
      user_id: null,
    }, {
      user_id: userId,
    }];
    filters[Op.and] = {
      [Op.or]: [
        sequelize.literal('CouponZones.zone_id = 1'),
        sequelize.literal('CouponZones.coupon_id IS  null')
      ],
    };
  } else {
    filters.user_id = null;
  }
  let coupons = await Coupon.findAll({
    where: {
      ...filters,
    },
    include: {
      model: CouponZone,
      attributes: [],
    },
    attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount', 'discount_upto', 'description', 'display'],
  });

这是它生成的查询。

SELECT `Coupon`.`id`, 
       `Coupon`.`coupon_code`, 
       `Coupon`.`discount_per`, 
       `Coupon`.`flat_discount`, 
       `Coupon`.`discount_upto`, 
       `Coupon`.`description`, 
       `Coupon`.`display` 
FROM   `coupons` AS `Coupon` 
       LEFT OUTER JOIN `coupon_zone_map` AS `CouponZones` 
                    ON `Coupon`.`id` = `CouponZones`.`coupon_id` 
WHERE  ( `Coupon`.`user_id` IS NULL 
          OR `Coupon`.`user_id` = 1 ) 
       AND ((CouponZones.zone_id = 1 OR CouponZones.coupon_id IS  null)) 
       AND `Coupon`.`is_active` = true 
       AND `Coupon`.`is_external` = false; 

【讨论】:

  • 在左连接表中几乎没有多少点可以从中选择任何列
  • @Strawberry 我不需要该表中的任何列,只需要根据它们进行过滤。也许我应该尝试使用through 和多对多关联?
  • 这通常是一个 INNER JOIN
【解决方案2】:

使用 UNION

你可以像下面这样写查询

SELECT coupons.* 
FROM   coupons, 
       coupon_city_map 
WHERE  coupons.id = coupon_city_map.coupon_id 
       AND coupon_city_map.city_id = 2 
UNION 
SELECT coupons.* 
FROM   coupons 
WHERE  coupons.id NOT IN(SELECT coupon_city_map.coupon_id 
                         FROM   coupon_city_map)

【讨论】:

  • 谢谢,但我认为 sequelize 不支持unions
  • 请注意,我们在 1992 年左右停止使用这种方式编写查询。为什么不加入我们?
猜你喜欢
  • 2020-07-07
  • 1970-01-01
  • 2013-05-26
  • 2021-05-20
  • 2020-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多