Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ MySQL _ Import i sumowanie istniejących CSV

Napisany przez: banki 26.06.2018, 22:55:16

Witam wszystkich,

mam problem z importem pliku CSV do bazy danych. Oczywiście zwykłe importowanie działa, ale nie zadowala mnie wynik tego importu.

Załóżmy że mam plik CSV wyglądający tak:
3504,72.00,011179239474,U23947,"nazwa 1"
3506,72.00,011179238910,U23891,"nazwa 2"
3508,72.00,011179238828,U23882,"nazwa 3"
3506,22.00,011179238910,U23891,"nazwa 2"

Jak widać 2 i 4 wiersz jest taki sam, różni się jedynie drugą kolumną. W moim kodzie importuje się jednak tylko jeden wiersz, ten, który jest wyżej. W tym wypadku 4 wiersz jest pomijany. Zwracane jest coś takiego:
3504,72.00,011179239474,U23947,"nazwa 1"
3506,72.00,011179238910,U23891,"nazwa 2"
3508,72.00,011179238828,U23882,"nazwa 3"

Efekt jaki chcę osiągnąć to:
3504,72.00,011179239474,U23947,"nazwa 1"
3506,94.00,011179238910,U23891,"nazwa 2"
3508,72.00,011179238828,U23882,"nazwa 3"

Czyli wartość np. z 2 kolumny się sumowała. 1 kolumna jest unikalna i niepowtarzalna, więc rekordy, które mają tą samą liczbę w kolumnie 1 powinny sumować wynik z kolumny 2. Nie wiem czy jasno wytłumaczyłem.

Do tej pory używałem do importu takiego kodu:

  1. <?php
  2. include 'dbConfig.php';
  3. if(http://www.php.net/isset($_POST['importSubmit'])){
  4. $csvMimes = http://www.php.net/array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel', 'text/plain');
  5. if(!http://www.php.net/empty($_FILES['file']['name']) && http://www.php.net/in_array($_FILES['file']['type'],$csvMimes)){
  6. if(http://www.php.net/is_uploaded_file($_FILES['file']['tmp_name'])){
  7.  
  8. $csvFile = http://www.php.net/fopen($_FILES['file']['tmp_name'], 'r');
  9. http://www.php.net/fgetcsv($csvFile);
  10. while(($line = http://www.php.net/fgetcsv($csvFile)) !== FALSE){
  11. $db->query("INSERT INTO produkty (numer, ilosc, ean, kod1, nazwa) VALUES ('".$line[0]."','".$line[1]."','".$line[2]."','".$line[3]."','".$line[4]."','".$line[5]."')");
  12. }
  13. http://www.php.net/fclose($csvFile);
  14. $qstring = '?status=sukces';
  15. }else{
  16. $qstring = '?status=error';
  17. }
  18. }else{
  19. $qstring = '?status=nieprawidlowy_plik';
  20. }
  21. }
  22. http://www.php.net/header("Location: index.php".$qstring);
  23. ?>



Z góry dzięki za jakiekolwiek podpowiedzi.

Napisany przez: mmmmmmm 27.06.2018, 07:13:30

https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

Napisany przez: banki 27.06.2018, 16:25:59

Dzięki za nakierowanie.

Poczytałem trochę o tym i poprawiłem kod, który jednak nie działa. Efekt jest taki sam.

  1. <?php
  2. include 'dbConfig.php';
  3. if(http://www.php.net/isset($_POST['importSubmit'])){
  4. $csvMimes = http://www.php.net/array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel', 'text/plain');
  5. if(!http://www.php.net/empty($_FILES['file']['name']) && http://www.php.net/in_array($_FILES['file']['type'],$csvMimes)){
  6. if(http://www.php.net/is_uploaded_file($_FILES['file']['tmp_name'])){
  7.  
  8. $csvFile = http://www.php.net/fopen($_FILES['file']['tmp_name'], 'r');
  9. http://www.php.net/fgetcsv($csvFile);
  10. while(($line = http://www.php.net/fgetcsv($csvFile)) !== FALSE){
  11. $db->query("INSERT INTO produkty (numer, ilosc, ean, kod1, nazwa) VALUES ('".$line[0]."','".$line[1]."','".$line[2]."','".$line[3]."','".$line[4]."','".$line[5]."')
  12. ON DUPLICATE KEY UPDATE ilosc = VALUES(ilosc)"
  13. ");
  14. }
  15. fclose($csvFile);
  16. $qstring = '?status=sukces';
  17. }else{
  18. $qstring = '?status=error';
  19. }
  20. }else{
  21. $qstring = '?status=nieprawidlowy_plik';
  22. }
  23. }
  24. header("Location: index.php".$qstring);
  25. ?>


dodałem do kodu
"ON DUPLICATE KEY UPDATE ilosc = VALUES(ilosc)"
myślałem że to zsumuje wartości kolumny ilosc dla klucza numer a tak na prawdę różnicy nie ma żadnej.

Napisany przez: nospor 27.06.2018, 16:30:00

Tak sie w mysql dodaje wartosci:
pole = pole + 5
gdzie 5 to wartosc 5 ktora chcesz dodac do pola pole.

Podobnie sie sumuje w kazdym innym czy to jezyku czy to bazie danych.


Zas
pole = 5
zawsze nadpisuje wartosc pola pole wartoscia 5. To jest dosc logiczne i dziala tak samo rowniez wszedzie

Napisany przez: banki 27.06.2018, 16:57:36

Tak faktycznie, głupio trochę to napisałem. W tej chwili ostatnią wartość dodaje z listy. Tylko jak zrobić sumowanie wszystkich liczb z kolumny dla jednego KEYa? Próbowałem z SUM lecz nie przechodziło

Napisany przez: nospor 27.06.2018, 17:00:07

No przeciez w poprzednim poscie ci napisalem jak sie SUMUJE. Ty zas masz tam ciagle nadpisywanie temu ci wpisuje ostatnia wartosc. Zmien na to co ci napisalem.

Napisany przez: banki 27.06.2018, 17:47:09

No tak, tylko że ja nie wiem jaka tam będzie wartość dodana i nie mogę zrobić sobie +1, +2 czy +10. Może być 20 a może być i 30. Plik CSV, który importuje może mieć 3 wartości z jednym kluczem.

Mogę mieć CSV który wygląda tak:
3504,72.00,011179239474,U23947,"nazwa 1"
3506,72.00,011179238910,U23891,"nazwa 2"
3508,72.00,011179238828,U23882,"nazwa 3"
3506,22.00,011179238910,U23891,"nazwa 2"

i wynik dla 3506 musi być 94 (dla 2 kolumny), a inny CSV może mieć
3504,72.00,011179239474,U23947,"nazwa 1"
3506,72.00,011179238910,U23891,"nazwa 2"
3508,72.00,011179238828,U23882,"nazwa 3"
3506,22.00,011179238910,U23891,"nazwa 2"
3506,22.00,011179238910,U23891,"nazwa 2"
i wtedy wynik musi mieć 116

Napisany przez: mmmmmmm 28.06.2018, 07:21:55

ON DUPLICATE KEY UPDATE ilosc = ilosc + VALUES(ilosc)
a dla pewności
ON DUPLICATE KEY UPDATE ilosc = Coalesce(ilosc, 0) + VALUES(Coalesce(ilosc,0))

Napisany przez: banki 28.06.2018, 09:07:09

u mnie zadziałało to:

ON DUPLICATE KEY UPDATE ilosc = ilosc+$line[1]

z VALUES i z Coalesce() nic się nie dzieje

Pojawił się przy tym kolejny problem. Problemem jest jeśli plik CSV jest oddzielany średnikiem ; a nie przecinkiem.

Zmieniając fgetcsv($csvFile) na fgetcsv($csvFile, 0, ';') aby rozdzielało po średnikach, wali się wszystko. Nie wczytuje w ogóle do bazy nic.

Usuwając ON DUPLICATE KEY UPDATE ładuje się plik ze średnikami. Wygląda jakby ON DUPLICATE KEY UPDATE kolidował ze średnikami ... możliwe?

Napisany przez: Pyton_000 28.06.2018, 09:18:13

Nie. Wyświetl sobie wygenerowane zapytanie to będziesz wiedział dlaczego się sypie.

Napisany przez: banki 28.06.2018, 09:23:43

Ok, udało się. Dzięki wszystkim za pomoc.

Końcowo kod wygląda tak:

  1. <?php
  2. include 'dbConfig.php';
  3. if(http://www.php.net/isset($_POST['importSubmit'])){
  4. $csvMimes = http://www.php.net/array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel', 'text/plain');
  5. if(!http://www.php.net/empty($_FILES['file']['name']) && http://www.php.net/in_array($_FILES['file']['type'],$csvMimes)){
  6. if(http://www.php.net/is_uploaded_file($_FILES['file']['tmp_name'])){
  7.  
  8. $csvFile = http://www.php.net/fopen($_FILES['file']['tmp_name'], 'r');
  9. http://www.php.net/fgetcsv($csvFile);
  10. while(($line = http://www.php.net/fgetcsv($csvFile, 0, ';')) !== FALSE){
  11. $db->query("INSERT INTO produkty (numer, ilosc, ean, kod1, nazwa) VALUES ('".$line[0]."','".$line[1]."','".$line[2]."','".$line[3]."','".$line[4]."','".$line[5]."')
  12.  
  13. ON DUPLICATE KEY UPDATE ilosc = ilosc+'".$line[1]."'
  14. ");
  15. }
  16. http://www.php.net/fclose($csvFile);
  17. $qstring = '?status=sukces';
  18. }else{
  19. $qstring = '?status=error';
  20. }
  21. }else{
  22. $qstring = '?status=nieprawidlowy_plik';
  23. }
  24. }
  25. http://www.php.net/header("Location: index.php".$qstring);
  26. ?>

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)