Avatar billede pfp Nybegynder
14. april 2006 - 12:25 Der er 7 kommentarer og
1 løsning

SP: Vælg nærmeste værdi

Hej,

Jeg sidder og forsøge at lave en SP som kan hente en pris for en vare ud fra min database. Det specielle ved denne pris er at den afhænger af hvor mange af varen man ønsker at købe.

Så jeg har 2 tabeller:
- Items (her ligger prisen for 1 stk.)
- Prices (her ligger alle priser, som er kædet sammen et givent antal).

Prices tabellen kunne f.eks. se sådan ud:
DATA:
--------------------------------------------
ItemId        Quantity    UnitPrice
--------------------------------------------
1001        2        400
1001        3        350
1001        5        300
1001        10        175
--------------------------------------------


RESULTATER VED INPUT AF QUANTITY OG ITEMID:
--------------------------------------------
Quantity    UnitPrice
--------------------------------------------
2        400
4        350
6        300
8        300
10        175
--------------------------------------------

Mit egentlige spørgsmål går så på hvordan jeg finder den række i tabellen som det givne input (@Quantity) matcher på. I ovenstående datatabel, skal Quantity = 4 gerne returnere data fra samme række som Quantity = 3, fordi man ikke har "opfyldt" nok til at opnå prisen for Quantity = 5.

Giver det nogen mening? I så fald vil jeg gerne høres Jeres bud på hvordan jeg får udvalgt den rigtige række.

Jeg har indtil videre nedenstående, men "hjertet" af proceduren mangler:

CREATE PROCEDURE sp_GetPrice
      @ItemId bigint,
      @Quantity int
AS
BEGIN
    /* FIND DEN RIGTIGE ENHEDSPRIS HVIS ANTAL > 1 */
    IF @Quantity > 1
        BEGIN
            /* HER MANGLER JEG AT UDVÆLGE DEN RIGTIGE */
        END
   
    /* HVIS ANTAL = 1 SKAL DEN ALM. ENHEDSPRIS BLOT HENTES UD */
    ELSE
        BEGIN
              SELECT Price AS UnitPrice FROM Items
              WHERE ItemId = @ItemId
        END
END
Avatar billede arne_v Ekspert
14. april 2006 - 13:35 #1
jeg tænker i baner af:

SELECT TOP 1 unitprice
FROM tabel
WHERE quantity <= @quantity
ORDER BY quantity DESC
Avatar billede pfp Nybegynder
14. april 2006 - 15:46 #2
Ja nu ser det jo let ud..:) Det var lige hvad der skulle til..

Jeg har et tillægsspørgsmål, hvis det er ok.. (jeg smider gerne flere point?)

CREATE PROCEDURE GetCart
    @ShopId bigint,
    @GUID nvarchar(36)
AS
    BEGIN
        SELECT Items.Title, Items.Price, Items.SymbolicName, Carts.* FROM Items
        INNER JOIN Carts ON Items.ItemId = Carts.ItemId
        WHERE Carts.ShopId = @ShopId
        AND Carts.Guid = @GUID
    END

    BEGIN
        EXEC sp_GetPrice <varenr>, <antal>
    END

Kan jeg på nogen måde kombinere de 2 blokke, så jeg får en række indeholdende både varens detaljer og prisen?
Avatar billede arne_v Ekspert
14. april 2006 - 16:38 #3
den ser lidt tricky ud

men med brug af en subquery og case where maa det kunne lade sig goere

jeg vil skulle eksperimentere lidt med den for at komme med noget SQL

jeg kan muligvis kigge paa det senere idag
Avatar billede pfp Nybegynder
14. april 2006 - 16:57 #4
Det ville jeg være meget taknemlig for. Jeg må lige prøve at grave i min database bog, det kan være jeg kan finde noget ud fra dine stikord om "case where" og "subquery"
Avatar billede arne_v Ekspert
15. april 2006 - 04:00 #5
1> CREATE TABLE cart (
2>    itemid INTEGER NOT NULL,
3>    quantity INTEGER,
4>    PRIMARY KEY(itemid)
5> )
6> GO
1>
2> CREATE TABLE items (
3>    itemid INTEGER NOT NULL,
4>    itemname VARCHAR(50),
5>    unitprice DECIMAL(12,2),
6>    PRIMARY KEY(itemid)
7> )
8> GO
1>
2> CREATE TABLE rebate (
3>    itemid INTEGER NOT NULL,
4>    quantity INTEGER NOT NULL,
5>    unitprice DECIMAL(12,2),
6>    PRIMARY KEY(itemid,quantity)
7> )
8> GO
1>
2> INSERT INTO cart VALUES(1, 1)
3> GO
(1 row affected)
1> INSERT INTO cart VALUES(2, 10)
2> GO
(1 row affected)
1>
2> INSERT INTO items VALUES(1,'A',200.00)
3> GO
(1 row affected)
1> INSERT INTO items VALUES(2,'B',100.00)
2> GO
(1 row affected)
1>
2> INSERT INTO rebate VALUES(2, 2, 90.00)
3> GO
(1 row affected)
1> INSERT INTO rebate VALUES(2, 4, 80.00)
2> GO
(1 row affected)
1> INSERT INTO rebate VALUES(2, 8, 70.00)
2> GO
(1 row affected)
1> INSERT INTO rebate VALUES(2, 16, 60.00)
2> GO
(1 row affected)
1>
2> SELECT itemname,quantity,unitprice
3> FROM cart JOIN items ON cart.itemid=items.itemid
4> GO
itemname                                          quantity    unitprice
-------------------------------------------------- ----------- --------------
A                                                            1        200.00
B                                                          10        100.00

(2 rows affected)
1>
2> SELECT itemname,quantity,unitprice,CASE WHEN quantity = 1 THEN unitprice ELSE afterrebate END AS unitpriceafterrebate
3> FROM (cart INNER JOIN items ON cart.itemid=items.itemid) LEFT JOIN (SELECT rebate.itemid,MIN(unitprice) AS afterrebate
4>                                                                    FROM rebate INNER JOIN cart ON rebate.itemid=cart.itemid
5>                                                                    WHERE rebate.quantity<=cart.quantity
6>                                                                    GROUP BY rebate.itemid) x ON cart.itemid=x.itemid
7> GO
itemname                                          quantity    unitprice            unitpriceafterrebate
-------------------------------------------------- ----------- --------------        --------------------
A                                                            1        200.00                      200.00
B                                                          10        100.00                      70.00

(2 rows affected)
1>
2> SELECT itemname,quantity,unitprice,ISNULL(afterrebate,unitprice) AS unitpriceafterrebate
3> FROM (cart INNER JOIN items ON cart.itemid=items.itemid) LEFT JOIN (SELECT rebate.itemid,MIN(unitprice) AS afterrebate
4>                                                                    FROM rebate INNER JOIN cart ON rebate.itemid=cart.itemid
5>                                                                    WHERE rebate.quantity<=cart.quantity
6>                                                                    GROUP BY rebate.itemid) x ON cart.itemid=x.itemid
7> GO
itemname                                          quantity    unitprice            unitpriceafterrebate
-------------------------------------------------- ----------- --------------        --------------------
A                                                            1        200.00                      200.00
B                                                          10        100.00                      70.00

(2 rows affected)
1>
2> DROP TABLE cart
3> GO
1> DROP TABLE items
2> GO
1> DROP TABLE rebate
2> GO
Avatar billede arne_v Ekspert
15. april 2006 - 04:00 #6
jeg kan bedre lide ISNULL end CASE fordi den også virker selvom der ikke er rabat på 2 !
Avatar billede pfp Nybegynder
15. april 2006 - 17:04 #7
Det er bare helt perfekt det der Arne! Det virker ligenøjagtig efter hensigten.

Smider du et svar?
Avatar billede arne_v Ekspert
15. april 2006 - 17:14 #8
kommer her
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester