[{"data":1,"prerenderedAt":345},["ShallowReactive",2],{"navigation":3,"page-\u002Fen\u002Fcreating-datasets\u002Fgrain-lookups-and-joins":130,"\u002Fen\u002Fcreating-datasets\u002Fgrain-lookups-and-joins-surround":339,"comments-\u002Fen\u002Fcreating-datasets\u002Fgrain-lookups-and-joins":344},[4],{"title":5,"path":6,"stem":7,"children":8,"page":129},"En","\u002Fen","en",[9,53,87],{"title":10,"path":11,"stem":12,"children":13,"icon":52},"CRM Analytics Foundations","\u002Fen\u002Ffoundations","en\u002F1.foundations\u002F1.index",[14,16,20,24,28,32,36,40,44,48],{"title":15,"path":11,"stem":12},"Welcome & Dev Org",{"title":17,"path":18,"stem":19},"Graded Quiz","\u002Fen\u002Ffoundations\u002Fquiz","en\u002F1.foundations\u002F10.quiz",{"title":21,"path":22,"stem":23},"What Is CRM Analytics?","\u002Fen\u002Ffoundations\u002Fwhat-is-crm-analytics","en\u002F1.foundations\u002F2.what-is-crm-analytics",{"title":25,"path":26,"stem":27},"Architecture","\u002Fen\u002Ffoundations\u002Farchitecture-and-data-flow","en\u002F1.foundations\u002F3.architecture-and-data-flow",{"title":29,"path":30,"stem":31},"The Data Layer","\u002Fen\u002Ffoundations\u002Fthe-data-layer","en\u002F1.foundations\u002F4.the-data-layer",{"title":33,"path":34,"stem":35},"The Design Layer","\u002Fen\u002Ffoundations\u002Fthe-design-layer","en\u002F1.foundations\u002F5.the-design-layer",{"title":37,"path":38,"stem":39},"The Intelligence Layer","\u002Fen\u002Ffoundations\u002Fthe-intelligence-layer","en\u002F1.foundations\u002F6.the-intelligence-layer",{"title":41,"path":42,"stem":43},"Hands-On Tour","\u002Fen\u002Ffoundations\u002Fhands-on-tour","en\u002F1.foundations\u002F7.hands-on-tour",{"title":45,"path":46,"stem":47},"Six Adoption Steps","\u002Fen\u002Ffoundations\u002Fsix-steps-and-interview-prep","en\u002F1.foundations\u002F8.six-steps-and-interview-prep",{"title":49,"path":50,"stem":51},"Interview Questions","\u002Fen\u002Ffoundations\u002Finterview-questions","en\u002F1.foundations\u002F9.interview-questions","i-lucide-compass",{"title":54,"path":55,"stem":56,"children":57,"icon":86},"Setup & User Provisioning","\u002Fen\u002Fsetup","en\u002F2.setup\u002F1.index",[58,60,64,68,72,76,80,83],{"title":59,"path":55,"stem":56},"Provisioning Users",{"title":61,"path":62,"stem":63},"Licenses & Permissions","\u002Fen\u002Fsetup\u002Flicenses-and-permission-sets","en\u002F2.setup\u002F2.licenses-and-permission-sets",{"title":65,"path":66,"stem":67},"Integration User","\u002Fen\u002Fsetup\u002Fthe-integration-user","en\u002F2.setup\u002F3.the-integration-user",{"title":69,"path":70,"stem":71},"Security User","\u002Fen\u002Fsetup\u002Fthe-security-user","en\u002F2.setup\u002F4.the-security-user",{"title":73,"path":74,"stem":75},"Analytics Settings","\u002Fen\u002Fsetup\u002Fanalytics-settings","en\u002F2.setup\u002F5.analytics-settings",{"title":77,"path":78,"stem":79},"Hands-On Access","\u002Fen\u002Fsetup\u002Fhands-on-assigning-access","en\u002F2.setup\u002F6.hands-on-assigning-access",{"title":17,"path":81,"stem":82},"\u002Fen\u002Fsetup\u002Fquiz","en\u002F2.setup\u002F7.quiz",{"title":49,"path":84,"stem":85},"\u002Fen\u002Fsetup\u002Finterview-questions","en\u002F2.setup\u002F8.interview-questions","i-lucide-settings-2",{"title":88,"path":89,"stem":90,"children":91,"icon":128},"Creating Datasets","\u002Fen\u002Fcreating-datasets","en\u002F3.creating-datasets\u002F1.index",[92,94,97,101,105,109,113,117,121,125],{"title":93,"path":89,"stem":90},"What Is a Dataset?",{"title":17,"path":95,"stem":96},"\u002Fen\u002Fcreating-datasets\u002Fquiz","en\u002F3.creating-datasets\u002F10.quiz",{"title":98,"path":99,"stem":100},"The Data Landscape","\u002Fen\u002Fcreating-datasets\u002Fthe-data-landscape","en\u002F3.creating-datasets\u002F2.the-data-landscape",{"title":102,"path":103,"stem":104},"Upload a CSV","\u002Fen\u002Fcreating-datasets\u002Fload-data-from-csv","en\u002F3.creating-datasets\u002F3.load-data-from-csv",{"title":106,"path":107,"stem":108},"Grain, Lookups & Joins","\u002Fen\u002Fcreating-datasets\u002Fgrain-lookups-and-joins","en\u002F3.creating-datasets\u002F4.grain-lookups-and-joins",{"title":110,"path":111,"stem":112},"Dataset Builder","\u002Fen\u002Fcreating-datasets\u002Fbuild-with-dataset-builder","en\u002F3.creating-datasets\u002F5.build-with-dataset-builder",{"title":114,"path":115,"stem":116},"Run the Dataflow","\u002Fen\u002Fcreating-datasets\u002Frun-and-troubleshoot-the-dataflow","en\u002F3.creating-datasets\u002F6.run-and-troubleshoot-the-dataflow",{"title":118,"path":119,"stem":120},"Build with a Recipe","\u002Fen\u002Fcreating-datasets\u002Fbuild-the-same-dataset-with-a-recipe","en\u002F3.creating-datasets\u002F7.build-the-same-dataset-with-a-recipe",{"title":122,"path":123,"stem":124},"Combine Datasets","\u002Fen\u002Fcreating-datasets\u002Fcombine-datasets","en\u002F3.creating-datasets\u002F8.combine-datasets",{"title":49,"path":126,"stem":127},"\u002Fen\u002Fcreating-datasets\u002Finterview-questions","en\u002F3.creating-datasets\u002F9.interview-questions","i-lucide-database",false,{"id":131,"title":132,"access":133,"body":134,"description":333,"extension":334,"interview":133,"links":133,"meta":335,"navigation":336,"passScore":133,"path":107,"quiz":133,"seo":337,"stem":108,"video":133,"__hash__":338},"docs\u002Fen\u002F3.creating-datasets\u002F4.grain-lookups-and-joins.md","Grain, Lookups, and Joins: The Mental Model",null,{"type":135,"value":136,"toc":324},"minimark",[137,141,159,164,173,188,203,207,217,241,246,257,261,270,293,307,311,314,317],[138,139,132],"h1",{"id":140},"grain-lookups-and-joins-the-mental-model",[142,143,144,145,149,150,154,155,158],"p",{},"This lesson has no video on purpose — it's the concept to slow down and ",[146,147,148],"em",{},"internalize"," before you build anything. Every dataset problem I've debugged over the years traces back to one of two things: the wrong ",[151,152,153],"strong",{},"grain",", or a ",[151,156,157],{},"join"," that quietly multiplied rows. Get this right and the tools in the next lessons become obvious.",[160,161,163],"h2",{"id":162},"what-is-grain","What is grain?",[142,165,166,169,170],{},[151,167,168],{},"Grain"," is the question: ",[146,171,172],{},"what does one row represent?",[142,174,175,176,179,180,183,184,187],{},"When you build a dataset \"about opportunities,\" the grain is one row per ",[151,177,178],{},"opportunity",". That's your ",[151,181,182],{},"core object"," — your lowest, most detailed level. Everything else you bring in (the account, the owner) is ",[146,185,186],{},"supporting information"," attached to that opportunity row. The grain never changes: one opportunity, one row.",[189,190,192],"tip",{"icon":191},"i-lucide-ruler",[142,193,194,195,198,199,202],{},"Say it out loud before you build: ",[151,196,197],{},"\"one row of this dataset is one _____.\""," Opportunity. Case. Account. Activity. If you can't finish that sentence cleanly, you're not ready to build the dataset yet — you're still deciding what it's ",[146,200,201],{},"about",".",[160,204,206],{"id":205},"start-from-the-lowest-object","Start from the lowest object",[142,208,209,210],{},"Here's the rule that saves you every time: ",[151,211,212,213,216],{},"start with your lowest-grain object and look ",[146,214,215],{},"up"," the hierarchy.",[142,218,219,220,223,224,228,229,232,233,236,237,240],{},"In Salesforce, an Opportunity ",[151,221,222],{},"looks up"," to an Account (via ",[225,226,227],"code",{},"AccountId",") and to a User owner (via ",[225,230,231],{},"OwnerId","). An Account sits ",[146,234,235],{},"higher"," — one account has ",[146,238,239],{},"many"," opportunities. So:",[242,243],"lesson-cards",{":columns":244,":items":245},"2","[{\"title\":\"Start with Opportunity ✅\",\"icon\":\"i-lucide-circle-check\",\"description\":\"From an opportunity you can look up to its Account and its owning User. One row per opportunity, enriched with account and user detail. Exactly what you want.\"},{\"title\":\"Start with Account ❌\",\"icon\":\"i-lucide-circle-x\",\"description\":\"From an account you can only look up — but there's nothing above it here. You can't reach 'down' to opportunities. You'd be stuck with one row per account.\"}]",[142,247,248,249,252,253,256],{},"This is why the object you start with is a ",[146,250,251],{},"design decision",", not an afterthought. If your dashboard is about opportunities, start with Opportunity. If you genuinely need one-row-per-account, that's a ",[151,254,255],{},"different dataset"," with a different grain — and that's fine, just be deliberate about it.",[160,258,260],{"id":259},"lookups-vs-joins","Lookups vs joins",[142,262,263,264,266,267,202],{},"You'll see the word ",[151,265,157],{}," in the tools, but for baseline datasets what you almost always want is a ",[151,268,269],{},"lookup",[271,272,273,284],"ul",{},[274,275,276,277,279,280,283],"li",{},"A ",[151,278,269],{}," attaches fields from a higher-level, \"parent\" object onto each child row. Bring the account's name and industry onto every opportunity — ",[151,281,282],{},"without changing the grain",". One opportunity stays one row.",[274,285,276,286,288,289,292],{},[151,287,157],{}," (in the fuller relational sense) can match rows many-to-many and ",[151,290,291],{},"multiply"," them. Join opportunities to their line items and suddenly one opportunity becomes five rows — one per line item. Sometimes that's what you want; often it's a bug that inflates your sums.",[189,294,296],{"icon":295},"i-lucide-triangle-alert",[142,297,298,299,302,303,306],{},"The classic mistake: you join a parent to a child expecting one row and get many, so every ",[225,300,301],{},"sum(Amount)"," is now double- or triple-counted. When a total looks too big, ",[151,304,305],{},"check your grain first."," Nine times out of ten a lookup got treated like a fan-out join.",[160,308,310],{"id":309},"why-dataset-builder-feels-safe","Why Dataset Builder feels \"safe\"",[142,312,313],{},"The next lessons build the same dataset two ways. The tools differ in exactly this area:",[242,315],{":columns":244,":items":316},"[{\"title\":\"Dataset Builder → lookups\",\"icon\":\"i-lucide-shield-check\",\"description\":\"It only lets you look *up* the relationship tree and figures out the join keys for you. Hard to get the grain wrong — which is why beginners should start here.\"},{\"title\":\"Recipes → full control\",\"icon\":\"i-lucide-sliders-horizontal\",\"description\":\"You choose the objects, the join type, and the keys yourself. Far more powerful, but you own the grain — and the mistakes.\"}]",[142,318,319,320,323],{},"There's a dedicated deep-dive on lookups, grain, and joins in the Data Manager \u002F data-expert material, and it's worth watching once you're comfortable here. But the one thing to carry into the next lessons is this: ",[151,321,322],{},"decide your grain first, start from the lowest object, and prefer lookups that keep one row per record."," Now let's build that opportunities dataset with Dataset Builder.",{"title":325,"searchDepth":326,"depth":327,"links":328},"",1,2,[329,330,331,332],{"id":162,"depth":327,"text":163},{"id":205,"depth":327,"text":206},{"id":259,"depth":327,"text":260},{"id":309,"depth":327,"text":310},"The one concept that makes or breaks a CRM Analytics dataset: grain. Understand grain, why you start from your lowest-level object, and how lookups and joins pull related data onto each row without multiplying it.","md",{},{"title":106},{"title":132,"description":333},"MkVuJseHFLT6ND9W-F2FM5nBU8mk--vSoj_8I6ite0I",[340,342],{"title":102,"path":103,"stem":104,"description":341,"children":-1},"Create a CRM Analytics dataset by uploading a CSV file. Walk through the upload flow, review dimensions, measures, and dates, control field types with the metadata schema, and automate uploads with Dataset Utils.",{"title":110,"path":111,"stem":112,"description":343,"children":-1},"Use Dataset Builder to create an opportunities dataset from Salesforce data. Start from the lowest-grain object, walk relationships up to Account and User, pick fields, and let it write the dataflow for you.",[],1783475168096]