אתגר SQL מספר 6# - ההזמנות מהקטגוריה הגבוהה ביותר

בעבר יצרתי פלייליסט ביוטיוב עם אתגרי SQL ופתרונות. בשבוע שעבר התיישבתי להקליט פרק נוסף, אבל הפעם עם כמה טוויסטים:

1. את הסרטון צילמתי ב-One Shot, בלי עצירות או עריכות.
2. את התרגיל? גיליתי רק ברגע שבו התחלתי לפתור אותו – פשוט ביקשתי מצ'ט ג'יפיטי שיג'נרט לי אתגר ויצאתי לדרך.

אני מאמין שיש המון ערך מוסף בלראות מישהו מתמודד עם אתגר בזמן אמת – טועה, מתקן, ומסביר את החשיבה שמאחורי הפתרון. זה לא תמיד נראה "חלק", ומצטלם יפה, אבל זו בדיוק המציאות שממנה לומדים הכי הרבה. תהנו 🙂

התרגיל

נתונה טבלה המתארת הזמנות מלקוחות. עליכם לכתוב שאילתה שמחזירה את כל הלקוחות שביצעו הזמנה שבה כל המוצרים שהוזמנו הם מהקטגוריה היקרה ביותר בטבלה (הקטגוריה בעלת המחיר הממוצע הגבוה ביותר).

עליכם להחזיר את המידע הבא:

  • שם הלקוח
  • מזהה הזמנה
  • קטגוריה
  • סך כל ההוצאה על ההזמנה

סקריפט ליצירת הטבלה

				
					<xmp>DROP TABLE IF EXISTS Orders;
CREATE TABLE Orders (
    OrderID INT,
    CustomerName VARCHAR(100),
    ProductName VARCHAR(100),
    Category VARCHAR(50),
    Price DECIMAL(10, 2),
    Quantity INT
);

INSERT INTO Orders (OrderID, CustomerName, ProductName, Category, Price, Quantity)
VALUES
(1, 'Alice', 'Laptop', 'Electronics', 1000.00, 1),
(1, 'Alice', 'Mouse', 'Electronics', 50.00, 2),
(2, 'Bob', 'T-Shirt', 'Clothing', 20.00, 3),
(2, 'Bob', 'Jeans', 'Clothing', 40.00, 1),
(3, 'Charlie', 'Smartphone', 'Electronics', 800.00, 1),
(3, 'Charlie', 'Charger', 'Electronics', 25.00, 1),
(4, 'Diana', 'Notebook', 'Stationery', 5.00, 4),
(4, 'Diana', 'Pen', 'Stationery', 2.00, 10),
(5, 'Eve', 'Dress', 'Clothing', 100.00, 1),
(5, 'Eve', 'Shoes', 'Clothing', 150.00, 1),
(6, 'Frank', 'Monitor', 'Electronics', 300.00, 2),
(6, 'Frank', 'Keyboard', 'Electronics', 80.00, 1),
(7, 'Grace', 'Backpack', 'Stationery', 30.00, 1),
(7, 'Grace', 'Laptop', 'Electronics', 1000.00, 1);
</xmp>
				
			

פתרונות

				
					<xmp>-- By Ram Kedem as shown in the video
;WITH highest_cat AS 
	(
	SELECT category, AVG(price) AS avg_price, 
					 DENSE_RANK() OVER (ORDER BY AVG(price) DESC) AS 'dr'
	FROM   orders 
	GROUP BY category
	)
SELECT   orderID, customerName, 
         COUNT(DISTINCT category) AS 'cnt_d', 
		 MAX(category) AS 'max_c',
		 SUM(price) AS 'total_price'
FROM     orders
GROUP BY orderID, customerName
HAVING   MAX(category) IN (SELECT category FROM highest_cat WHERE dr = 1)
AND      COUNT(DISTINCT category) = 1 </xmp>
				
			
				
					<xmp>-- Adjusted solution, taking the Quantity into account

;WITH highest_cat AS 
	(
	SELECT category, AVG(price) AS avg_price, 
					 DENSE_RANK() OVER (ORDER BY AVG(price) DESC) AS 'dr'
	FROM   orders 
	GROUP BY category
	)
SELECT   orderID, customerName, 
         COUNT(DISTINCT category) AS 'cnt_d', 
		 MAX(category) AS 'max_c',
		 SUM(price * quantity) AS 'total_price'
FROM     orders
GROUP BY orderID, customerName
HAVING   MAX(category) IN (SELECT category FROM highest_cat WHERE dr = 1)
AND      COUNT(DISTINCT category) = 1 </xmp>
				
			
				
					<xmp>-- By ChatGPT
WITH CategoryAvgPrice AS (
    SELECT
        Category,
        AVG(Price) AS AvgPrice
    FROM
        Orders
    GROUP BY
        Category
),
MaxCategory AS (
    SELECT
        Category
    FROM
        CategoryAvgPrice
    WHERE
        AvgPrice = (SELECT MAX(AvgPrice) FROM CategoryAvgPrice)
),
OrdersWithTotal AS (
    SELECT
        OrderID,
        CustomerName,
        Category,
        SUM(Price * Quantity) AS TotalPrice,
        COUNT(DISTINCT Category) AS DistinctCategories
    FROM
        Orders
    GROUP BY
        OrderID, CustomerName, Category
)
SELECT DISTINCT
    o.CustomerName,
    o.OrderID,
    o.Category,
    o.TotalPrice
FROM
    OrdersWithTotal o
INNER JOIN
    MaxCategory mc
ON
    o.Category = mc.Category
WHERE
    o.DistinctCategories = 1;
</xmp>
				
			

דברו איתנו