ClickHouse 实现数组交并差计算
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ClickHouse 实现数组交并差计算相关的知识,希望对你有一定的参考价值。
参考技术A ClickHouse 实现数组交并差计算函数:arrayIntersect(arr1,arr2,...)
功能说明:计算 arr1,arr2等数组元素交集。
返回值:交集元素子数组。
SQL 实例:
输出:
noIntersect: []
hasIntersect: [3,2]
组合使用函数来实现arrayDistinct(arrayConcat(a, b))。
SQL 实例:
输出:
a: [1,2]
b: [2,3]
res: [1,2,3]
差集的实现要有一些技术含量了(感觉 ClickHouse 后面应该内置数组差集计算函数,实现类似arrayExcept() 函数),需要使用数组交集函数arrayIntersect() 结合高阶函数 arrayMap()和 arrayFilter()来组合实现。
SQL 实例:
输出:
a: [1,2]
b: [2,3]
res: [1]
另外, ClickHouse 中有集合交(INTERSECT)、并(UNION)、差(EXCEPT)的SQL子句关键字,可以实现数组的交并差运算。实例 SQL 如下。
输出:2
输出:
1
2
3
输出:1
上述[1,2]和[2,3]分别表示要求差集的数组
数据函数解释:
arrayIntersect表示多个数组求交集
arrayConcat表示连接多个数组为一个数组
arrayDistinct表示将多个数组元素去重组合为一个数组
arrayMap表示使用lambda函数转换
arrayFilter表示使用lambda函数过滤
https://clickhouse.tech/docs/zh/sql-reference/functions/higher-order-functions/
有序单链表的(交并差)运算
#include "stdafx.h" #include "malloc.h" typedef struct Node { char data; Node *next; }List;
// 创建单链表 void CreateList(List *&L, char a[], int n) { List *s,*r; L = (List *)malloc(sizeof(List)); L->next = NULL; r = L; for (int i = 0; i < n; i++) { s = (List *)malloc(sizeof(List)); s->data = a[i]; r->next = s; r = s; } r->next = NULL; }
// 使用了排序算法中的插入排序 void Sort(List *&head) { List *p = head->next, *q, *r; // p指向第一个节点 if(p!=NULL) { r = p->next; // r指向第二个节点 p->next = NULL; // p的后继节点为NULL p = r; // p指向第一个节点 while (p!=NULL) { r = p->next; q = head; while (q->next!=NULL &&q->next->data<p->data) { q = q->next; } p->next = q->next; q->next = p; p = r; } } } // 求两个集合并集 void Union(List *La, List *Lb, List *&Lc) { List *la = La->next, *lb = Lb->next,*tc,*s; Lc = (List *)malloc(sizeof(List)); tc = Lc; // 在进行比较 if (la != NULL && lb != NULL) { while (la != NULL && lb != NULL) { s = (List *)malloc(sizeof(List)); if (la->data > lb->data) { // la节点大于lb节点 s->data = lb->data; tc->next = s; tc = s; lb = lb->next; } else if(la->data<lb->data) { // la节点小于lb节点 s->data = la->data; tc->next = s; tc = s; la = la->next; } else { s->data = la->data; tc->next = s; tc = s; la = la->next; lb = lb->next; } } } // 剩余节点(la与lb必定有一个是NULL) if (lb != NULL) { la = lb; } while (la!=NULL) { s = (List *)malloc(sizeof(List)); s->data = la->data; tc->next = s; tc = s; la = la->next; } tc->next = NULL; } // 求两个集合的并集 void InterSect(List *La, List *Lb, List *&Lc) { List *la = La->next, *lb,*tc, *s; Lc = (List *)malloc(sizeof(List)); tc = Lc; while (la!=NULL) { lb = Lb->next; // 根据链表为有序链表过滤一部分比较节点 while (lb!=NULL && lb->data<la->data) { lb = lb->next; } if (lb != NULL && lb->data == la->data) { s = (List *)malloc(sizeof(List)); s->data = la->data; tc->next = s; tc = s; } la = la->next; } tc->next = NULL; } // 求差集,即a-b,去掉a链表中与b链表的交集 void Subs(List *La, List *Lb, List *&Lc) { List *la = La->next, *lb, *tc, *s; Lc = (List *)malloc(sizeof(List)); tc = Lc; while (la!=NULL) { lb = Lb->next; // 根据链表为有序链表过滤一部分比较节点 while (lb!=NULL && lb->data<la->data) { lb = lb->next; } // 去掉Lb链表与La链表的交集部分 if (!(lb != NULL &&la->data == lb->data)) { s = (List *)malloc(sizeof(List)); s->data = la->data; tc->next = s; tc = s; } la = la->next; } tc->next = NULL; }
1、使用单链表对集合进行交、并、差的运算,重点在于对单链表进行排序,排序后的单链表在进行运算,可以减少节点的比较优化时间复杂度。
以上是关于ClickHouse 实现数组交并差计算的主要内容,如果未能解决你的问题,请参考以下文章
WideTableMultiDimSQLParser 解析说明:ClickHouse / Hive 数组交并差运算
ClickHouse高级数据查询SQL: WITH/JOIN/IN/INTO OUTFILE/嵌套子查询/交并差计算等