#havingFilter
#add-having-filter
地域でグループ化した後、売上が 100 万を超える高業績地域を絞り込む
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.add('sales', node => { node.setAggregate({"func":"sum"}).setOperator('gt').setValue(1000000); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#add-multiple-having-filter
複数の Having 条件をチェーン追加し、売上と利益が高い地域を絞り込む
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(1000000)).add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(200000)); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#clear-having-filter
すべての Having フィルター条件をクリアし、全量のグループ集計結果を表示
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": [
{
"id": "having-1",
"field": "sales",
"op": "gt",
"value": 1000000,
"aggregate": {
"func": "sum"
}
},
{
"id": "having-2",
"field": "profit",
"op": "gt",
"value": 200000,
"aggregate": {
"func": "sum"
}
}
]
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.clear(); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-array-value-with-in-operator
配列値を持つ Having フィルターで 'in' 演算子への変換を発生させる例
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 10
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => {
builder.havingFilter.add('sales', node => {
node.setOperator('=').setValue([100, 200, 300]);
});
}
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-array-value-with-not-in-operator
配列値を持つ Having フィルターで 'not in' 演算子への変換を発生させる例
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 10
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => {
builder.havingFilter.add('sales', node => {
node.setOperator('!=').setValue([100, 200]);
});
}
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-clear-and-rebuild
既存の having 条件をクリアして新しいグループフィルターを再構築し、ユーザーがフィルターパネルをリセットして再設定する流れを再現
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "amount",
"alias": "数量",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": [
{
"id": "old-1",
"field": "sales",
"op": "gt",
"value": 999999,
"aggregate": {
"func": "sum"
}
}
]
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.clear(); builder.havingFilter.addGroup('and', g => { g.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gte').setValue(100000)); g.addGroup('or', sub => { sub.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(20000)); sub.add('amount', n => n.setAggregate({"func":"sum"}).setOperator('gte').setValue(50)); }); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-deeply-nested-groups
3 層のネストグループ: OR(AND(売上 > 50 万, 利益 > 5 万), AND(数量 > 100, 平均割引 < 0.3)) による複雑な業務フィルター
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "province",
"alias": "都道府県"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "amount",
"alias": "数量",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "discount",
"alias": "平均割引",
"encoding": "yAxis",
"aggregate": {
"func": "avg"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 10
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.addGroup('or', root => { root.addGroup('and', g1 => { g1.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(500000)); g1.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(50000)); }); root.addGroup('and', g2 => { g2.add('amount', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(100)); g2.add('discount', n => n.setAggregate({"func":"avg"}).setOperator('lt').setValue(0.3)); }); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-empty-dsl-compose-target
空の DSL から builder で where/having/measures/dimensions を組み立て、sum と countDistinct 集計を含む having 条件を構成
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "line",
"dimensions": [],
"measures": [],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.chartType.changeChartType('table'); builder.theme.setTheme('light'); builder.locale.setLocale('zh-CN'); builder.whereFilter.add('profit', n => n.setOperator('<').setValue(0)); const whereConds = builder.whereFilter.getConditions(); whereConds.get(0).set('id', 'c84825ed-547a-48f0-b4d9-55ebe53aab8c'); builder.havingFilter.clear(); builder.havingFilter.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('lt').setValue(-100000)); builder.havingFilter.add('province', n => n.setAggregate({"func":"countDistinct"}).setOperator('gt').setValue(4)); const havingConds = builder.havingFilter.getConditions(); havingConds.get(0).set('id', 'a6f2f16a-e0fc-4bdc-9729-bbe3a105cfca'); havingConds.get(1).set('id', '01c004d2-4041-40ee-a18b-a18fc0cea416'); builder.measures.add('sales', n => n.setAlias('sales').setEncoding('yAxis').setAggregate({"func":"sum"})); builder.measures.add('country_or_region', n => n.setAlias('country_or_region').setEncoding('yAxis').setAggregate({"func":"count"})); const measures = builder.dsl.get('measures'); measures.get(0).set('id', 'a5ba6c4a-31dc-4b2c-a38f-9f23c2bbe850'); measures.get(1).set('id', '49f3b33d-4ede-436c-8be9-a51619236916'); builder.dimensions.add('area', n => n.setAlias('area')); const dimensions = builder.dsl.get('dimensions'); dimensions.get(0).set('id', 'c3583433-a2cc-4234-85ff-75ae2472b674'); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-field-not-in-measures-and-dimensions
空の DSL を初期化し、builder で area ディメンションと sales 指標だけを追加し、measures/dimensions にない profit フィールドを having で使用
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "line",
"dimensions": [],
"measures": [],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.chartType.changeChartType('bar'); builder.dimensions.add('area', n => n.setAlias('Region')); builder.measures.add('sales', n => n.setAlias('Sales').setEncoding('yAxis').setAggregate({"func":"sum"})); builder.havingFilter.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(100000)); builder.limit.setLimit(20); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-find-and-update
having 条件を追加した後、find で検索してしきい値と演算子を動的に更新し、対話的な条件調整を再現
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "column",
"dimensions": [
{
"field": "product_type",
"alias": "カテゴリ"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(100000)).add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(10000)); const json = builder.havingFilter.toJSON().conditions; const salesId = json[0].id; const profitId = json[1].id; builder.havingFilter.update(salesId, n => { n.setOperator('gte').setValue(500000); }); builder.havingFilter.update(profitId, n => { n.setOperator('gte').setValue(50000); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-group-add-to-existing
既存の having グループに新しい条件を追加し、段階的にフィルタールールを絞り込む流れを再現
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "amount",
"alias": "数量",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": [
{
"id": "group-1",
"op": "or",
"conditions": [
{
"id": "cond-1",
"field": "sales",
"op": "gt",
"value": 500000,
"aggregate": {
"func": "sum"
}
}
]
}
]
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.updateGroup('group-1', group => { group.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(100000)); group.add('amount', n => n.setAggregate({"func":"sum"}).setOperator('gte').setValue(200)); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-group-remove-condition
既存の having グループから特定条件を削除し、ユーザーがフィルター項目を取り消す流れを再現
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "column",
"dimensions": [
{
"field": "product_type",
"alias": "カテゴリ"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": [
{
"id": "group-1",
"op": "and",
"conditions": [
{
"id": "cond-1",
"field": "sales",
"op": "gt",
"value": 100000,
"aggregate": {
"func": "sum"
}
},
{
"id": "cond-2",
"field": "profit",
"op": "gt",
"value": 10000,
"aggregate": {
"func": "sum"
}
}
]
}
]
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.updateGroup('group-1', group => { group.remove('cond-1'); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-mix-filters-and-groups
独立条件と OR グループを混在: 売上 > 50 万 AND (利益 > 10 万 OR 数量 >= 30)
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "amount",
"alias": "数量",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(500000)).addGroup('or', group => { group.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(100000)); group.add('amount', n => n.setAggregate({"func":"sum"}).setOperator('gte').setValue(30)); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-multi-dimension-aggregate
カテゴリと地域の 2 ディメンションでグループ化し、平均割引 20% 未満かつ総売上 10 万超の組み合わせを抽出
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "product_type",
"alias": "カテゴリ"
},
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "discount",
"alias": "平均割引",
"encoding": "yAxis",
"aggregate": {
"func": "avg"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 10
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.addGroup('and', g => { g.add('discount', n => n.setAggregate({"func":"avg"}).setOperator('lt').setValue(0.2)); g.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(100000)); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-nested-groups
ネストグループ: AND(売上 > 100 万, OR(利益 > 20 万, 数量 >= 50))
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "amount",
"alias": "数量",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.addGroup('and', outer => { outer.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(1000000)); outer.addGroup('or', inner => { inner.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(200000)); inner.add('amount', n => n.setAggregate({"func":"sum"}).setOperator('gte').setValue(50)); }); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-or-group
OR グループで売上または利益が高い地域を絞り込む
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.addGroup('or', group => { group.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(1000000)); group.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(200000)); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-scatter-profit-analysis
散布図分析: カテゴリ別に高利益率かつ取引数 20 件超のカテゴリを絞り込み、優良業務を特定
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "scatter",
"dimensions": [
{
"field": "product_sub_type",
"alias": "サブカテゴリ"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "xAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "amount",
"alias": "数量",
"encoding": "size",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 10
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.addGroup('and', g => { g.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(0)); g.add('amount', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(20)); g.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(10000)); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-update-group-operator
既存の Having グループの論理演算子を AND から OR に更新
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": [
{
"id": "group-1",
"op": "and",
"conditions": [
{
"id": "cond-1",
"field": "sales",
"op": "gt",
"value": 1000000,
"aggregate": {
"func": "sum"
}
},
{
"id": "cond-2",
"field": "profit",
"op": "gt",
"value": 200000,
"aggregate": {
"func": "sum"
}
}
]
}
]
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.updateGroup('group-1', group => { group.setOperator('or'); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#having-with-where-combined
where と having の組み合わせ: 先に where で事務用品カテゴリを絞り込み、having で売上 5 万超または利益 1 万超の都道府県を抽出
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "column",
"dimensions": [
{
"field": "province",
"alias": "都道府県"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 10
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.whereFilter.add('product_type', n => n.setOperator('=').setValue('办公用品')); builder.havingFilter.addGroup('or', g => { g.add('sales', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(50000)); g.add('profit', n => n.setAggregate({"func":"sum"}).setOperator('gt').setValue(10000)); }); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}#remove-having-filter
余分な Having フィルター条件を削除し、利益フィルターだけを保持
import { VBI, VBIChartBuilder } from '@visactor/vbi'
import { DEMO_CONNECTOR_ID, VSeedRender } from '@components'
import { useEffect, useState } from 'react'
export default () => {
const [result, setResult] = useState<any>(null)
useEffect(() => {
const run = async () => {
const builder = VBI.chart.create({
...{
"connectorId": "demoSupermarket",
"chartType": "bar",
"dimensions": [
{
"field": "area",
"alias": "地域"
}
],
"measures": [
{
"field": "sales",
"alias": "売上",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
},
{
"field": "profit",
"alias": "利益",
"encoding": "yAxis",
"aggregate": {
"func": "sum"
}
}
],
"whereFilter": {
"id": "root",
"op": "and",
"conditions": []
},
"havingFilter": {
"id": "root",
"op": "and",
"conditions": [
{
"id": "having-1",
"field": "sales",
"op": "gt",
"value": 1000000,
"aggregate": {
"func": "sum"
}
},
{
"id": "having-2",
"field": "profit",
"op": "gt",
"value": 200000,
"aggregate": {
"func": "sum"
}
}
]
},
"theme": "light",
"locale": "ja-JP",
"version": 1,
"limit": 20
},
connectorId: DEMO_CONNECTOR_ID,
})
const applyBuilder = (builder: VBIChartBuilder) => { builder.havingFilter.remove('having-1'); }
applyBuilder(builder)
setResult(await builder.buildVSeed())
}
run()
}, [])
if (!result) return <div>Loading...</div>
return <VSeedRender vseed={result} />
}