2013-04-09 11 views
7

Potrzebuję utworzyć widok, który ma kolumnę o nazwie nr_wiersza, w której zostanie wstawiony numer wiersza, podobnie jak automatyczny przyrost w normalnej tabeli.Utwórz widok z kolumną num_rows - MySQL

Jestem naprawdę nowy z widokami, więc proszę o mnie. Powiedzmy mam to normalne tabeli:

| country | name | age | price | 
-------------------------------- 
| US  | john | 22 | 20 | 
| France | Anne | 10 | 15 | 
| Sweden | Alex | 49 | 10 | 

i tak dalej ...

widok Chcę utworzyć to:

| country | name | price | row_num | 
    ------------------------------------ 
    | US  | john | 20 | 1 | 
    | France | Anne | 10 | 2 | 
    | Sweden | Alex | 5 | 3 | 

I tak dalej ...

Potrafię wygenerować liczbę wierszy za pomocą jednego wyboru:

SELECT @i:[email protected]+1 AS row_num, testing.country, testing.name, testing.price 
FROM testing testing,(SELECT @i:=0) derivedTable 
order by name 

Ale moim problemem jest połączenie powyższego zapytania z zapytaniem tworzącym widok. To w połączeniu kwerenda Próbuję:

CREATE OR REPLACE view vwx (country, name, price, num_row) AS SELECT mytable.country, mytable.name, mytable.price, @i:[email protected]+1 AS row_number 
    FROM testing testing,(SELECT @i:=0) derivedTable 
    order by name; 

pojawia się następujący błąd: # 1351 - widok na SELECT zawiera zmienną lub parametr

wiem, że nie można używać wewnątrz select select z widokami, ale nie widzę innego sposobu na zrobienie tego widoku tak, jak chcę, ale jestem pewien, że jest sposób, aby to zrobić, ale po prostu nie wiem jak. Prawdopodobnie z funkcjami lub procedurami, ale jestem naprawdę dla nich nowy, więc nie jestem zadowolony z tworzenia funkcji lub procedur w mysql.

Mam nadzieję, że wyraziłem się jasno, w przeciwnym razie z przyjemnością wyjaśnię więcej szczegółów.

+1

Dlaczego nie ma automatycznego inkrementacji, jak "zwykły stół", z którego można korzystać? – Neal

+0

Ponieważ nie zaprojektowałem tego stołu, a ten stół zawiera już tysiące i tysiące zapisów. Poza tym nie pozwalają mi niczego zmienić na tym stole, dlatego używam widoków. – dazito

+0

Ah, i jeszcze jeden szczegół @ Nie, że zapomniałem wspomnieć, że widok jest tworzony z klauzulą ​​where, nie umieściłem go tam, ponieważ myślałem, że to nie jest ważny szczegół. – dazito

Odpowiedz

5

Znalazłem rozwiązanie tego problemu:

najpierw utworzyć funkcję:

delimiter // 

CREATE FUNCTION `func_inc_var_session`() RETURNS int 
    NO SQL 
    NOT DETERMINISTIC 
    begin 
     SET @var := @var + 1; 
     return @var; 
    end 
    // 

delimiter ; 

następnie ustawić @ var do numeru, który chcesz zacząć. W tym przypadku zero.

SET @var=0;

Następnie utworzyć widok, jak następuje:

CREATE OR REPLACE VIEW myview (place, name, hour, price, counter) 
AS SELECT place, name, hour, price, func_inc_var_session() 
FROM yourtable 
WHERE input_conditions_here; 

Sztuką jest to, że można zobaczyć NULL w kolumnie licznika. Jeśli tak się stanie, ustaw ponownie @var na swój numer, a następnie ponownie WYBIERZ *, a kolumna liczników będzie poprawnie wypełniona.

+0

Kiedy robię to z "order by" w "input_conditions_here", otrzymuję func_inc_var_session() w złej kolejności. Myślę, że tutaj potrzebna jest podkwerenda. – user43326

-1
CREATE OR REPLACE view vwx (country, name, price, num_row) AS 
SELECT country, name, price, @index := @index + 1 AS num_row 
FROM testing, (SELECT @index := 0) temp 
+4

Nie można obawiać się, ponieważ używa ona zmiennej w widoku tworzenia, pojawia się ten sam błąd co poprzednio: 'Kod błędu: 1351. WYBÓR widoku zawiera zmienną lub parametr \t 0.000 sek.' – dazito

0

próby zastosowania tej kwerendy do widoku -

CREATE TABLE testing (
    id int(11) NOT NULL DEFAULT 0, 
    country varchar(255) DEFAULT NULL, 
    name varchar(255) DEFAULT NULL, 
    age int(11) DEFAULT NULL, 
    price int(11) DEFAULT NULL, 
    PRIMARY KEY (id) 
); 

INSERT INTO testing(id, country, name, age, price) VALUES 
    (1, 'US', 'john', 22, 20), 
    (2, 'France', 'Anne', 10, 15), 
    (3, 'Sweden', 'Alex', 49, 10), 
    (4, 'France', 'Anne', 11, 16); 

SELECT 
    t1.*, COUNT(*) row_num 
FROM testing t1 
    LEFT JOIN testing t2 
    ON t2.name < t1.name OR (t2.name = t1.name AND t2.id <= t1.id) 
GROUP BY t1.name, t1.id; 

+----+---------+------+------+-------+---------+ 
| id | country | name | age | price | row_num | 
+----+---------+------+------+-------+---------+ 
| 3 | Sweden | Alex | 49 | 10 |  1 | 
| 2 | France | Anne | 10 | 15 |  2 | 
| 4 | France | Anne | 11 | 16 |  3 | 
| 1 | US  | john | 22 | 20 |  4 | 
+----+---------+------+------+-------+---------+ 
  • To zapytanie nie używa żadnych zmiennych użytkownika, więc wotks w widokach.
  • Dodatkowy warunek w klauzuli ON pomaga wprowadzić zduplikowane wartości w polu name.
+0

W Twojej 5 linii, gdzie masz 'NA t2.name dazito

+0

Och, przepraszam. Miałem na myśli unikalną kolumnę ID. Dodam pełny przykład. – Devart

1

Lub spróbuj this-> utworzyć tabelę tymczasową i wstawić dane do niego jak poniżej

CREATE OR REPLACE TEMPORARY TABLE myview (
    country VARCHAR(250), 
    name VARCHA(50), 
    price VARCHAR(50), 
    row_num int(11) 
); 

SET @row_num = 0; 
INSERT INTO myview (country,name,price,row_num) 
    SELECT @row_num:[email protected]_num+1 
     as country,name,price,row_num 
    FROM testing; 

SELECT * FROM myview; 

+---------+------+------+-------+---------+ 
| country | name | age | price | row_num | 
+---------+------+------+-------+---------+ 
| Sweden | Alex | 49 | 10 |  1 | 
| France | Anne | 10 | 15 |  2 | 
| France | Anne | 11 | 16 |  3 | 
| US  | john | 22 | 20 |  4 | 
+---------+------+------+-------+---------+ 
2

Próbowałem przykład funkcji func_inc_var_session.

Wystąpił mały problem podczas inicjalizacji zmiennej sesji, którą rozwiązałem przy użyciu funkcji mysql IFNULL.

Poniżej ulepszonej funkcji func_inc_var_session.

CREATE DEFINER=`root`@`localhost` FUNCTION `func_inc_var_session`() RETURNS int(11) 
begin 
    SET @var := IFNULL(@var,0) + 1; 
    return @var; 
end 
+1

Uwaga: jeśli korzystasz z funkcji dwa lub więcej razy w jednym zapytaniu (np. Przy JOIN), będzie ona nadal zwiększać zmienną. –

0

Dodanie numeru wiersza w wyniku zapytania - nie potrzebne View - One Query

SELECT country, name, price, @ID := @ID + 1 AS row_num 
FROM testing, 
    (SELECT @ID := 0) temp 

Dodaj następujące do MySQL connectionString: Allow User Variables=True;

Nie dodawaj "Krzyż Dołącz do zapytania "w zapytaniu, aby zaktualizować zmienną @ID.

+0

Witamy w SO. Prawidłowe sformatowanie kodu w odpowiedziach jest bardzo pomocne :-) – Blackbam

+0

OP chce uzyskać wynik jako widok, a twoja odpowiedź nie będzie działać jako widok. – user43326

1

Podczas korzystania z rozwiązania @dazito może pojawić się problem z ciągle wzrastającym wzrostem liczby zapytań do zapytania, na przykład gdy aplikacja ponownie wykorzystuje sesję, np. Z JPA/Hibernate. Np

Query 1:

 
| country | name | price | row_num | 
------------------------------------ 
| US  | john | 20 | 1 | 
| France | Anne | 10 | 2 | 
| Sweden | Alex | 5 | 3 | 

Query 2:

 
| country | name | price | row_num | 
------------------------------------ 
| US  | john | 20 | 4 | 
| France | Anne | 10 | 5 | 
| Sweden | Alex | 5 | 6 | 

itp

Rozwiązaniem tego problemu jest połączenie głównego zapytanie z (jednorazowe) wywołać funkcję licznika i sparametryzować funkcję (parametr "reset" poniżej), aby powiadomić go, że jest to pierwsze połączenie.

 
delimiter // 
CREATE FUNCTION `func_inc_var_session`(reset BIT) RETURNS int 
    NO SQL 
    NOT DETERMINISTIC 
    begin 
     IF reset THEN 
     SET @var := 0; 
     ELSE 
     SET @var := IFNULL(@var,0) + 1; 
     END IF; 
     return @var; 
    end 
    // 
delimiter ; 

Teraz można wywołać funkcję w zapytaniu widok z parametrem resetu ustawiony na 1, aby ustawić zmienną licznika z funkcji z powrotem do 0, i 0, aby zwiększyć licznik. Funkcja zostanie sprawdzony tylko raz 1 jako parametr podczas łączenia się z nim, jak poniżej:

 
CREATE OR REPLACE VIEW country_view (country, name, price, row_num) 
AS SELECT country, name, price, func_inc_var_session(0) 
FROM country 
JOIN (SELECT func_inc_var_session(1)) r 

Teraz masz gwarantowaną ilość wiersz 1, 2, 3 za każdym razem.

Powiązane problemy