SQL转XQuery遇阻:基于Mondial XML实现带岛屿湖泊的大洲面积统计
Solving Your Mondial XML Lake Area Statistics Problem with XQuery
Got it, let's break down how to build this XQuery solution step by step—focusing on the group by, sum, and join-like operations you need, plus handling cross-continent country prorating.
Key Requirements Recap
We need to:
- Only count lakes that have at least one island.
- Split lake area proportionally across continents if the lake's country spans multiple continents.
- Group the results by continent and sum the prorated lake areas.
Complete XQuery Solution
xquery version "3.0"; (: Step 1: Extract lakes that have at least one island, with their area and country code :) let $island_lakes := for $lake in doc("mondial.xml")//lake[island] where number($lake/@area) > 0 : Skip lakes with no area data return ( <lake_info> <area>{number($lake/@area)}</area> <country_code>{$lake/@country}</country_code> </lake_info> ) (: Step 2: Calculate continent area ratios for each country (handles cross-continent nations) :) let $country_continent_ratios := for $country in doc("mondial.xml")//country let $total_country_area := number($country/@area) where $total_country_area > 0 : Avoid division by zero for $encompassed in $country/encompassed let $continent_area := number($encompassed/@area) let $proration_ratio := $continent_area div $total_country_area return ( <country_continent> <car_code>{$country/@car_code}</car_code> <continent>{$encompassed/@continent}</continent> <ratio>{$proration_ratio}</ratio> </country_continent> ) (: Step 3: Join lake data with continent ratios, compute prorated area per continent :) let $prorated_lake_areas := join $island_lakes with $country_continent_ratios on $island_lakes/country_code eq $country_continent_ratios/car_code return ( <continent_lake_area> <continent>{$country_continent_ratios/continent}</continent> <prorated_amount>{$island_lakes/area * $country_continent_ratios/ratio}</prorated_amount> </continent_lake_area> ) (: Step 4: Group by continent and sum the prorated areas :) for $continent in distinct-values($prorated_lake_areas/continent) let $total_area := sum($prorated_lake_areas[continent eq $continent]/prorated_amount) order by $continent return ( <continent_summary> <name>{$continent}</name> <total_island_lake_area>{format-number($total_area, '#,##0.00')}</total_island_lake_area> </continent_summary> )
Key Details Explained
- Filtering lakes with islands: We use
lake[island]to target only lakes that have at least one<island>child node. - Handling cross-continent countries: For each country, we calculate the ratio of its area in each continent (using the
<encompassed>nodes) to its total area. This ratio is used to split the lake's area across relevant continents. - Join operation: XQuery 3.0's
joinfunction mimics SQL's INNER JOIN, linking lakes to their country's continent data. If your environment doesn't support XQuery 3.0, replace the join with nested loops:let $prorated_lake_areas := for $lake in $island_lakes for $ccr in $country_continent_ratios where $lake/country_code eq $ccr/car_code return ( <continent_lake_area> <continent>{$ccr/continent}</continent> <prorated_amount>{$lake/area * $ccr/ratio}</prorated_amount> </continent_lake_area> ) - Grouping and summing: We use
distinct-valuesto get unique continent names, then sum all prorated amounts for each continent. Theformat-numberfunction makes the final totals easier to read.
Notes
- Make sure the path to
mondial.xmlis correct for your environment (adjustdoc("mondial.xml")if using a database collection instead of a local file). - We added checks for zero area values to avoid division by zero errors.
内容的提问来源于stack exchange,提问作者Schytheron
相关产品推荐
相关产品推荐

