1"use strict";(self.webpackChunkzed_docs=self.webpackChunkzed_docs||[]).push([[10269],{3905:function(e,t,a){a.d(t,{Zo:function(){return u},kt:function(){return d}});var n=a(67294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?o(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):o(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function s(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},o=Object.keys(e);for(n=0;n<o.length;n++)a=o[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)a=o[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var i=n.createContext({}),p=function(e){var t=n.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},u=function(e){var t=p(e.components);return n.createElement(i.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,o=e.originalType,i=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=p(a),d=r,h=m["".concat(i,".").concat(d)]||m[d]||c[d]||o;return a?n.createElement(h,l(l({ref:t},u),{},{components:a})):n.createElement(h,l({ref:t},u))}));function d(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=a.length,l=new Array(o);l[0]=m;var s={};for(var i in t)hasOwnProperty.call(t,i)&&(s[i]=t[i]);s.originalType=e,s.mdxType="string"==typeof e?e:r,l[1]=s;for(var p=2;p<o;p++)l[p]=a[p];return n.createElement.apply(null,l)}return n.createElement.apply(null,a)}m.displayName="MDXCreateElement"},96920:function(e,t,a){a.r(t),a.d(t,{assets:function(){return u},contentTitle:function(){return i},default:function(){return d},frontMatter:function(){return s},metadata:function(){return p},toc:function(){return c}});var n=a(83117),r=a(80102),o=(a(67294),a(3905)),l=["components"],s={sidebar_position:7,sidebar_label:"Lateral Subqueries"},i="Lateral Subqueries",p={unversionedId:"language/lateral-subqueries",id:"version-v1.16.0/language/lateral-subqueries",title:"Lateral Subqueries",description:"Lateral subqueries provide a powerful means to apply a Zed query",source:"@site/versioned_docs/version-v1.16.0/language/lateral-subqueries.md",sourceDirName:"language",slug:"/language/lateral-subqueries",permalink:"/docs/v1.16.0/language/lateral-subqueries",draft:!1,editUrl:"https://github.com/brimdata/zed/edit/main/docs/language/lateral-subqueries.md",tags:[],version:"v1.16.0",sidebarPosition:7,frontMatter:{sidebar_position:7,sidebar_label:"Lateral Subqueries"},sidebar:"tutorialSidebar",previous:{title:"Search Expressions",permalink:"/docs/v1.16.0/language/search-expressions"},next:{title:"Shaping and Type Fusion",permalink:"/docs/v1.16.0/language/shaping"}},u={},c=[{value:"Lateral Scope",id:"lateral-scope",level:2},{value:"Lateral Expressions",id:"lateral-expressions",level:2}],m={toc:c};function d(e){var t=e.components,a=(0,r.Z)(e,l);return(0,o.kt)("wrapper",(0,n.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"lateral-subqueries"},"Lateral Subqueries"),(0,o.kt)("p",null,"Lateral subqueries provide a powerful means to apply a Zed query\nto each subsequence of values generated from an outer sequence of values.\
1nThe inner query may be ",(0,o.kt)("em",{parentName:"p"},"any Zed query")," and may refer to values from\nthe outer sequence."),(0,o.kt)("p",null,"Lateral subqueries are created using the scoped form of the\n",(0,o.kt)("a",{parentName:"p",href:"/docs/v1.16.0/language/operators/over"},(0,o.kt)("inlineCode",{parentName:"a"},"over")," operator")," and may be nested to arbitrary depth."),(0,o.kt)("p",null,"For example,"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-command"},"echo '{s:\"foo\",a:[1,2]} {s:\"bar\",a:[3]}' | zq -z 'over a with name=s => (yield {name,elem:this})' -\n")),(0,o.kt)("p",null,"produces"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-output"},'{name:"foo",elem:1}\n{name:"foo",elem:2}\n{name:"bar",elem:3}\n')),(0,o.kt)("p",null,"Here the lateral scope, described below, creates a subquery"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"yield {name,elem:this}\n")),(0,o.kt)("p",null,"for each subsequence of values derived from each outer input value.\nIn the example above, there are two input values:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'{s:"foo",a:[1,2]}\n{s:"bar",a:[3]}\n')),(0,o.kt)("p",null,"which imply two subqueries derived from the ",(0,o.kt)("inlineCode",{parentName:"p"},"over")," operator traversing ",(0,o.kt)("inlineCode",{parentName:"p"},"a"),".\nThe first subquery thus operates on the input values ",(0,o.kt)("inlineCode",{parentName:"p"},"1, 2")," with the variable\n",(0,o.kt)("inlineCode",{parentName:"p"},"name"),' set to "foo" assigning ',(0,o.kt)("inlineCode",{parentName:"p"},"1")," and then ",(0,o.kt)("inlineCode",{parentName:"p"},"2")," to ",(0,o.kt)("inlineCode",{parentName:"p"},"this"),", thereby emitting"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'{name:"foo",elem:1}\n{name:"foo",elem:2}\n')),(0,o.kt)("p",null,"and the second subquery operators on the input value ",(0,o.kt)("inlineCode",{parentName:"p"},"3")," with the variable\n",(0,o.kt)("inlineCode",{parentName:"p"},"name"),' set to "bar", emitting'),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'{name:"bar",elem:3}\n')),(0,o.kt)("p",null,"You can also import a parent-scope field reference into the inner scope by\nsimply referring to its name without assignment, e.g.,"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-command"},"echo '{s:\"foo\",a:[1,2]} {s:\"bar\",a:[3]}' | zq -z 'over a with s => (yield {s,elem:this})' -\n")),(0,o.kt)("p",null,"produces"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-output"},'{s:"foo",elem:1}\n{s:"foo",elem:2}\n{s:"bar",elem:3}\n')),(0,o.kt)("h2",{id:"lateral-scope"},"Lateral Scope"),(0,o.kt)("p",null,"A lateral scope has the form ",(0,o.kt)("inlineCode",{parentName:"p"},"=> ( <query> )")," and currently appears\nonly the context of an ",(0,o.kt)("a",{parentName:"p",href:"/docs/v1.16.0/language/operators/over"},(0,o.kt)("inlineCode",{parentName:"a"},"over")," operator"),",\nas illustrated above, and has the form:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"over ... with <elem> [, <elem> ...] => ( <query> )\n")),(0,o.kt)("p",null,"where ",(0,o.kt)("inlineCode",{parentName:"p"},"<elem>")," has either an assignment form"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"<var>=<expr>\n")),(0,o.kt)("p",null,"or a field reference form"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"<field>\n")),(0,o.kt)("p",null,"For each input value to the outer scope, the assignment form creates a binding\nbetween each ",(0,o.kt)("inlineCode",{parentName:"p"},"<expr>")," evaluated in the outer scope and each ",(0,o.kt)("inlineCode",{parentName:"p"},"<var>"),", which\nrepresents a new symbol in the inner scope of the ",(0,o.kt)("inlineCode",{parentName:"p"},"<query>"),".\nIn the field reference form, a single identifier ",(0,o.kt)("inlineCode",{parentName:"p"},"<field>")," refers to a field\nin the parent scope and makes that field's value available in the lateral scope\nwith the same name."),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"<query>"),", which may be any Zed query, is evaluated once per outer value\non the sequence generated by the ",(0,o.kt)("inlineCode",{parentName:"p"},"over")," expression. In the lateral scope,\nthe value ",(0,o.kt)("inlineCode",{parentName:"p"},"this")," refers to the inner sequence generated from the ",(0,o.kt)("inlineCode",{parentName:"p"},"over")," expressions.\nThis query runs to completion for each inner sequence and emits\neach subquery result as each inner sequence traversal completes."),(0,o.kt)("p",null,"This structure is powerful because ",(0,o.kt)("em",{parentName:"p"}
1,"any")," Zed query can appear in the body of\nthe lateral scope. In contrast to the ",(0,o.kt)("inlineCode",{parentName:"p"},"yield")," example, a sort could be\napplied to each subsequence in the subquery, where sort\nreads all values of the subsequence, sorts them, emits them, then\nrepeats the process for the next subsequence. For example,"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-command"},"echo '[3,2,1] [4,1,7] [1,2,3]' | zq -z 'over this => (sort this | collect(this))' -\n")),(0,o.kt)("p",null,"produces"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-output"},"[1,2,3]\n[1,4,7]\n[1,2,3]\n")),(0,o.kt)("h2",{id:"lateral-expressions"},"Lateral Expressions"),(0,o.kt)("p",null,"Lateral subqueries can also appear in expression context using the\nparenthesized form:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"( over <expr> [, <expr>...] [with <var>=<expr> [, ... <var>[=<expr>]] | <lateral> )\n")),(0,o.kt)("blockquote",null,(0,o.kt)("p",{parentName:"blockquote"},"Note that the parentheses disambiguate a lateral expression from a lateral\ndataflow operator.")),(0,o.kt)("p",null,"This form must always include a lateral scope as indicated by ",(0,o.kt)("inlineCode",{parentName:"p"},"<lateral>"),",\nwhich can be any dataflow operator sequence excluding ",(0,o.kt)("a",{parentName:"p",href:"/docs/v1.16.0/language/operators/from"},(0,o.kt)("inlineCode",{parentName:"a"},"from")," operators"),".\nAs with the ",(0,o.kt)("inlineCode",{parentName:"p"},"over")," operator, values from the outer scope can be brought into\nthe lateral scope using the ",(0,o.kt)("inlineCode",{parentName:"p"},"with")," clause."),(0,o.kt)("p",null,"The lateral expression is evaluated by evaluating each ",(0,o.kt)("inlineCode",{parentName:"p"},"<expr>")," and feeding\nthe results as inputs to the ",(0,o.kt)("inlineCode",{parentName:"p"},"<lateral>")," dataflow operators. Each time the\nlateral expression is evaluated, the lateral operators are run to completion,\ne.g.,"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-command"},"echo '[3,2,1] [4,1,7] [1,2,3]' | zq -z 'yield (over this | sum(this))' -\n")),(0,o.kt)("p",null,"produces"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-output"},"6\n12\n6\n")),(0,o.kt)("p",null,"This structure generalizes to any more complicated expression context,\ne.g., we can embed multiple lateral expressions inside of a record literal\nand use the spread operator to tighten up the output:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-command"},"echo '[3,2,1] [4,1,7] [1,2,3]' | zq -z '{...(over this | sort this | sorted:=collect(this)),...(over this | sum:=sum(this))}' -\n")),(0,o.kt)("p",null,"produces"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-mdtest-output"},"{sorted:[1,2,3],sum:6}\n{sorted:[1,4,7],sum:12}\n{sorted:[1,2,3],sum:6}\n")))}d.isMDXComponent=!0}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.