【tp6一对多查询,结果集显示主表信息加附表行数】【tp6 join 闭包一个临时查询结果】

2 篇文章 0 订阅
2 篇文章 0 订阅

tp6一对多查询,结果集显示主表信息加附表行数

场景

存在一个主表A,一个附表B,主表一对多附表,但主表中含有附表中没有对应的数据,同样,附表中含有主表中没有对应的数据,现需要查询的结果集,是主表和附表完全对应的数据,展示主表信息,以及每一行附表的匹配行数,并且查询需要以B表的某一个字段作为where条件。

样例

这是主表A表
A表主表示例这是附表B表
B表附表示例
A表中 sn 字段对应 B表中 sn_a 字段

想要的结果集:

snnamepriceb_num
2056244377033339380宝贝儿童蝴蝶面蔬菜钙铁锌胡萝卜鸡蛋彩蝶面片辅食无添加食盐46.035
3764948331774106024宝贝儿童蝴蝶面蔬菜钙铁锌胡萝卜鸡蛋彩蝶面片辅食无添加食盐47.746

编写SQL

1、使用子查询确认 inner join 链表后的数据集作为条件,以消除【主表中含有附表中没有对应的数据】和【附表中含有主表中没有对应的数据】

SELECT sn_a FROM pro_test_a a 

INNER JOIN pro_test_b b ON a.sn = b.sn_a 

WHERE b.time >=  1706748841 and  b.time <= 1706757178

这就得到了一对多状态下的所有 sn

2、联查条件中包含以上子查询,得到

SELECT a.sn,a.name,a.price

FROM pro_test_a a

WHERE a.sn IN (

   SELECT sn_a FROM pro_test_a a 

	INNER JOIN pro_test_b b ON a.sn = b.sn_a 

	WHERE b.time >=  1706748841 and  b.time <= 1706757178
    
)

此时结果集,仅差 b_num 没有出现,需要一个临时表,与A表联查

3、创建临时表,结果集出现 b_num

SELECT a.sn,a.name,a.price,c.b_num

FROM pro_test_a a

INNER JOIN 

	( SELECT a.sn,COUNT(*) as b_num 

	FROM pro_test_a a 
	
	INNER JOIN pro_test_b b ON a.sn = b.sn_a 

	WHERE b.time >=  1706748841 and  b.time <= 1706757178 

	GROUP BY a.sn ) 

	as c ON a.sn = c.sn
	
WHERE a.sn IN (

    SELECT sn_a FROM pro_test_a a 

	INNER JOIN pro_test_b b ON a.sn = b.sn_a 

	WHERE b.time >=  1706748841 and  b.time <= 1706757178
)

翻译成TP方法

//$test_a_model 是A表的实例化模型
$c_temp = $test_a_model
	->field('a.sn,COUNT(*) as b_num')
	->alias('a')
	->join('pro_test_b b','a.sn = b.sn_a')
	->where([
		['b.time','>=',1706748841],
		['b.time','<=',1706757178]
	])
	->group('a.sn')
	->buildSql();
$list = $test_a_model->field('a.sn,a.name,a.price,c.b_num')
	->alias('a')
	->join([$c_temp=>'c'],'a.sn = c.sn')
	->where(function($query) use ($test_a_model){
		$sn_list = $test_a_model
			->field('b.sn_a')
			->alias('a')
			->join('pro_test_b b','a.sn = b.sn_a')
			->where([
				['b.time','>=',1706748841],
				['b.time','<=',1706757178]
			])
			->group('a.sn')
			->select()->toArray();
			$sn_list = array_column($sn_list,'sn_a');
			$query->whereIn('a.sn',$sn_list);
	})
//	->buildSql()
	->select()
	->toArray();

运行代码验证

//buildSql后结果是
( SELECT `a`.`sn`,`a`.`name`,`a`.`price`,`c`.`b_num` 

FROM `pro_test_a` `a` 

INNER JOIN ( 

	SELECT a.sn,COUNT(*) as b_num 

	FROM `pro_test_a` `a` 

	INNER JOIN `pro_test_b` `b` ON `a`.`sn`=`b`.`sn_a` 

	WHERE  `b`.`time` >= '1706748841'  

	AND `b`.`time` <= '1706757178' 

	GROUP BY `a`.`sn` 
	
) `c` ON `a`.`sn`=`c`.`sn` 

WHERE  (  `a`.`sn` IN ('2056244377033339380','3764948331774106024') ) )
//下面的where闭包解析后直接出结果集了
//查询结果集
array (size=2)
  0 => 
    array (size=4)
      'sn' => string '2056244377033339380' (length=19)
      'name' => string '宝贝儿童蝴蝶面蔬菜钙铁锌胡萝卜鸡蛋彩蝶面片辅食无添加食盐' (length=84)
      'price' => string '46.03' (length=5)
      'b_num' => int 5
  1 => 
    array (size=4)
      'sn' => string '3764948331774106024' (length=19)
      'name' => string '宝贝儿童蝴蝶面蔬菜钙铁锌胡萝卜鸡蛋彩蝶面片辅食无添加食盐' (length=84)
      'price' => string '47.74' (length=5)
      'b_num' => int 6

!!!大功告成

测试数据SQL


//测试A表

CREATE TABLE `pro_test_a` (
  `id` int(11) NOT NULL,
  `sn` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT '',
  `name` varchar(300) COLLATE utf8mb4_unicode_ci DEFAULT '',
  `price` decimal(10,2) DEFAULT '0.00',
  `time` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='测试A表';

INSERT INTO `pro_test_a` (`id`, `sn`, `name`, `price`, `time`) VALUES
(1, '2056244377033339380', '宝贝儿童蝴蝶面蔬菜钙铁锌胡萝卜鸡蛋彩蝶面片辅食无添加食盐', '46.03', 1706716791),
(2, '3764362392235604137', '面条一箱装鸡蛋面整箱挂面龙须面超细面条营养速食劲道袋包邮', '0.00', 1706716794),
(3, '3764363652587254455', '宝贝无盐胡萝卜儿童面条营养无添加食盐早餐辅食营养超细挂面', '0.00', 1706716929),
(4, '3764384532504399038', '北京鸡蛋面龙须面超细面条挂面早餐方便速食劲道炒面主食细面', '25.48', 1706716720),
(5, '3764829746742312161', '宝贝儿童面条营养无添加食盐速食钙铁锌早餐无盐面条彩色挂面', '45.99', 1706716601),
(6, '3764850914747412022', '宝贝儿童面条果蔬营养蔬菜面无添加盐龙须面超细挂面辅食无盐', '33.83', 1706716348),
(7, '3764931843758397234', '宝贝儿童珍珠琪面无盐面片营养果蔬蔬菜面条彩琪面无添加食盐', '31.05', 1706716247),
(8, '3764948331774106024', '宝贝儿童蝴蝶面蔬菜钙铁锌胡萝卜鸡蛋彩蝶面片辅食无添加食盐', '47.74', 1706715887),
(9, '3764952363482664149', '宝贝儿童面条营养无添加食盐速食钙铁锌早餐无盐面条彩色挂面', '0.00', 1706715851);

ALTER TABLE `pro_test_a`
  ADD PRIMARY KEY (`id`),
  ADD KEY `sn` (`sn`);

ALTER TABLE `pro_test_a`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10;



//测试B表

CREATE TABLE `pro_test_b` (
  `id` int(11) NOT NULL,
  `sn_a` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT '',
  `num` int(11) DEFAULT '0',
  `price` decimal(10,2) DEFAULT '0.00',
  `time` int(10) UNSIGNED DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `pro_test_b` (`id`, `sn_a`, `num`, `price`, `time`) VALUES
(1, '2056244377033339380', 1, '1.30', 1706748841),
(2, '2056244377033339380', 2, '4.00', 1706748841),
(3, '2056244377033339380', 2, '4.00', 1706748841),
(4, '2056244377033339380', 2, '4.00', 1706748841),
(5, '2056244377033339380', 2, '4.00', 1706748841),
(6, '3764832411369540336', 1, '7.60', 1706748839),
(7, '3764832411369540336', 1, '7.60', 1706748839),
(8, '3764832411369540336', 1, '1.30', 1706748839),
(9, '3764948331774106024', 1, '4.00', 1706757178),
(10, '3764948331774106024', 1, '4.00', 1706757178),
(11, '3764948331774106024', 1, '1.30', 1706757178),
(12, '3764948331774106024', 4, '4.00', 1706757178),
(13, '3764948331774106024', 1, '4.00', 1706757178),
(14, '3764948331774106024', 1, '4.00', 1706757178);

ALTER TABLE `pro_test_b`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `pro_test_b`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=24;
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值