JsonSQL Aggregat-Demo mit Filter

📊 JsonSQL Aggregat-Demo mit Filter

Diese interaktive Demo zeigt die Möglichkeiten von JsonSQL zur Analyse strukturierter JSON-Daten – ganz ohne klassische Datenbank.

Über das komfortable Filtermenü kannst du gezielt Produkte und Händler auswählen. Anschließend werden dir automatisch alle relevanten Statistiken wie Summe, Durchschnitt, Median, Minimum, Maximum, Spannweite, Varianz und Standardabweichung für numerische Felder wie Preis, Lagerbestand und Bewertung angezeigt – jeweils vor und nach dem Filter.

Zusätzlich kannst du Testdaten generieren und optional den Transaktionsmodus aktivieren, um Datenänderungen gesammelt zu speichern.



⏮️ Zurücksetzen
📋 Datentabelle (150 Einträge)
id product rating price vendor stock date
1 Kaffeemaschine
84.69 Otto 1340 2025-01-18
2 Kaffeemaschine
76.04 Otto 2008 2025-01-14
3 Kaffeemaschine
101.65 Amazon 4897 2025-03-31
4 Kaffeemaschine
101.35 MediaMarkt 4875 2024-11-05
5 Kaffeemaschine
76.51 Real 276 2024-11-15
6 Kaffeemaschine
90.98 Amazon 4920 2025-01-31
7 Kaffeemaschine
82.24 Real 2848 2025-03-07
8 Kaffeemaschine
89.69 Real 1494 2025-01-26
9 Kaffeemaschine
79.04 Real 2103 2025-03-23
10 Kaffeemaschine
85.55 Saturn 4453 2025-02-26
11 Kaffeemaschine
82.85 Saturn 1542 2025-03-27
12 Kaffeemaschine
103.38 eBay 1711 2024-12-01
13 Kaffeemaschine
90.5 Real 3868 2025-01-21
14 Kaffeemaschine
95.33 eBay 1054 2025-01-23
15 Kaffeemaschine
85.85 Aldi 594 2025-02-12
16 Kaffeemaschine
103.74 Lidl 487 2025-03-04
17 Kaffeemaschine
83.07 Otto 1332 2025-03-28
18 Kaffeemaschine
80.98 Real 4343 2024-12-07
19 Kaffeemaschine
100.37 eBay 3091 2024-11-15
20 Kaffeemaschine
86.54 eBay 2530 2025-01-19
21 Kaffeemaschine
105.37 Otto 2558 2024-12-21
22 Kaffeemaschine
77.9 Real 496 2025-02-03
23 Kaffeemaschine
101.41 Lidl 3207 2025-01-11
24 Kaffeemaschine
77.78 eBay 71 2025-03-01
25 Kaffeemaschine
77.69 MediaMarkt 3147 2025-01-07
26 Kaffeemaschine
81.67 Real 2656 2025-03-24
27 Kaffeemaschine
76.57 MediaMarkt 1545 2025-02-02
28 Kaffeemaschine
82.53 Lidl 2874 2025-02-12
29 Kaffeemaschine
94.08 Saturn 1297 2024-11-11
30 Kaffeemaschine
99.88 Amazon 3819 2024-12-21
31 Kaffeemaschine
97.46 Lidl 2543 2024-12-25
32 Kaffeemaschine
100.57 Amazon 1117 2025-01-23
33 Kaffeemaschine
96.96 Amazon 4485 2024-12-28
34 Kaffeemaschine
76.8 Amazon 4131 2025-03-07
35 Kaffeemaschine
95.95 MediaMarkt 557 2025-02-22
36 Kaffeemaschine
105.28 Amazon 1625 2025-01-09
37 Kaffeemaschine
84.2 Lidl 3697 2025-02-22
38 Kaffeemaschine
92.62 Real 3676 2024-12-02
39 Kaffeemaschine
100.18 Lidl 1046 2024-11-26
40 Kaffeemaschine
96.79 Real 62 2025-02-08
41 Kaffeemaschine
104.71 Otto 968 2025-03-31
42 Kaffeemaschine
90.48 Lidl 762 2025-03-21
43 Kaffeemaschine
87.54 Amazon 4996 2025-03-31
44 Kaffeemaschine
100.55 MediaMarkt 3472 2024-11-25
45 Kaffeemaschine
94.78 Amazon 2107 2025-03-13
46 Kaffeemaschine
77.74 eBay 4131 2024-12-21
47 Kaffeemaschine
99.21 Real 1561 2025-01-11
48 Kaffeemaschine
91.97 eBay 2539 2024-11-12
49 Kaffeemaschine
75.31 eBay 3100 2024-12-01
50 Kaffeemaschine
76.67 Aldi 3522 2024-11-17
51 Wasserkocher
39.95 Amazon 4599 2024-12-23
52 Wasserkocher
53.49 eBay 4909 2025-02-18
53 Wasserkocher
36.1 Aldi 4693 2024-12-17
54 Wasserkocher
45.12 Otto 3655 2025-03-26
55 Wasserkocher
35.84 Real 3503 2025-01-18
56 Wasserkocher
46.33 Aldi 4712 2025-03-30
57 Wasserkocher
44.09 MediaMarkt 3564 2025-03-17
58 Wasserkocher
55.99 Saturn 3776 2024-11-10
59 Wasserkocher
39.88 Lidl 1549 2025-02-16
60 Wasserkocher
37.46 Lidl 4287 2024-12-24
61 Wasserkocher
47.96 Otto 3608 2025-02-15
62 Wasserkocher
51.09 Aldi 1683 2025-01-10
63 Wasserkocher
36.79 Real 2246 2025-01-23
64 Wasserkocher
40.09 MediaMarkt 2903 2024-12-19
65 Wasserkocher
42.45 Aldi 1000 2025-03-09
66 Wasserkocher
42.27 Aldi 3426 2025-01-07
67 Wasserkocher
43.75 Lidl 263 2025-03-18
68 Wasserkocher
43.09 Otto 29 2025-02-07
69 Wasserkocher
48.12 Saturn 2233 2024-11-10
70 Wasserkocher
36.04 MediaMarkt 826 2025-03-27
71 Wasserkocher
41.47 Amazon 3280 2024-12-05
72 Wasserkocher
40.32 Lidl 1933 2025-03-07
73 Wasserkocher
55.18 MediaMarkt 4426 2025-01-07
74 Wasserkocher
44.12 Amazon 4624 2024-12-05
75 Wasserkocher
36.92 Real 3441 2025-01-29
76 Wasserkocher
36.11 Lidl 2670 2024-11-10
77 Wasserkocher
53.79 Lidl 1664 2025-01-22
78 Wasserkocher
48.12 Otto 134 2025-03-21
79 Wasserkocher
38.01 Real 2096 2024-11-11
80 Wasserkocher
55.59 Real 994 2024-12-31
81 Wasserkocher
55.32 eBay 4441 2025-03-08
82 Wasserkocher
46.72 Lidl 4384 2024-11-02
83 Wasserkocher
35.86 Lidl 4425 2025-02-05
84 Wasserkocher
45.84 Amazon 1455 2025-02-21
85 Wasserkocher
42.26 Otto 3379 2025-02-06
86 Wasserkocher
50.44 Saturn 2558 2025-01-17
87 Wasserkocher
43.05 Real 3786 2025-02-05
88 Wasserkocher
47.8 eBay 544 2024-11-01
89 Wasserkocher
48.12 Saturn 814 2025-03-09
90 Wasserkocher
40.94 MediaMarkt 636 2025-01-09
91 Wasserkocher
50.97 Amazon 730 2025-01-06
92 Wasserkocher
47.34 Saturn 4022 2025-02-10
93 Wasserkocher
39.18 Saturn 67 2024-12-28
94 Wasserkocher
53.31 Otto 1565 2024-12-09
95 Wasserkocher
50.34 Amazon 1935 2024-11-03
96 Wasserkocher
37.86 MediaMarkt 1551 2024-12-29
97 Wasserkocher
40.15 eBay 3397 2024-12-28
98 Wasserkocher
35.31 Amazon 4836 2024-12-09
99 Wasserkocher
51.2 MediaMarkt 2660 2025-03-25
100 Wasserkocher
37.66 eBay 1998 2025-01-06
101 Toaster
29.69 MediaMarkt 4582 2025-01-06
102 Toaster
20.47 Aldi 141 2025-03-20
103 Toaster
26.29 eBay 3838 2024-11-15
104 Toaster
20.38 Aldi 1943 2024-12-20
105 Toaster
28.6 Real 4856 2025-01-08
106 Toaster
19.2 Lidl 323 2024-12-25
107 Toaster
24.07 Lidl 2074 2025-02-19
108 Toaster
21.75 eBay 57 2025-02-24
109 Toaster
27.5 Real 3822 2024-11-28
110 Toaster
24.32 Otto 2154 2025-02-09
111 Toaster
26.22 Otto 4828 2025-01-24
112 Toaster
30.21 Aldi 2342 2024-11-14
113 Toaster
20.3 Amazon 2487 2025-01-15
114 Toaster
20.46 Amazon 119 2025-02-19
115 Toaster
29.58 Amazon 4583 2024-12-28
116 Toaster
30.03 Otto 474 2025-03-11
117 Toaster
19.9 Amazon 3584 2025-01-23
118 Toaster
23.38 MediaMarkt 3212 2024-11-22
119 Toaster
29.49 Amazon 1519 2024-11-30
120 Toaster
25.83 Lidl 1255 2025-02-27
121 Toaster
22.17 Otto 3080 2024-11-22
122 Toaster
26.86 Amazon 2483 2025-02-01
123 Toaster
19.78 Saturn 1669 2025-03-06
124 Toaster
26.01 Otto 4253 2024-12-24
125 Toaster
29.82 Otto 2057 2024-11-24
126 Toaster
29.95 Saturn 3855 2025-02-03
127 Toaster
22.18 Real 2554 2025-02-26
128 Toaster
29.03 Real 372 2024-11-10
129 Toaster
19.57 Amazon 4051 2024-11-24
130 Toaster
19.46 Amazon 3452 2025-02-02
131 Toaster
28.44 Aldi 4447 2024-12-13
132 Toaster
25.6 Amazon 2245 2024-12-06
133 Toaster
29.04 Saturn 4906 2024-11-18
134 Toaster
22.49 Aldi 3421 2025-01-08
135 Toaster
29.74 Otto 1837 2025-01-20
136 Toaster
24.65 Saturn 2887 2024-12-20
137 Toaster
21.87 Lidl 4403 2024-12-03
138 Toaster
21.63 Lidl 3358 2024-12-05
139 Toaster
29.48 Real 193 2024-12-10
140 Toaster
24.87 Aldi 156 2025-02-22
141 Toaster
26.84 Amazon 51 2024-11-12
142 Toaster
21.46 Aldi 3065 2024-12-11
143 Toaster
23.65 MediaMarkt 957 2024-12-15
144 Toaster
25.26 Lidl 4082 2025-01-09
145 Toaster
25.15 eBay 1123 2025-01-26
146 Toaster
25.65 Aldi 1264 2025-03-06
147 Toaster
22.83 Lidl 3822 2025-03-06
148 Toaster
27.67 Otto 2392 2025-02-15
149 Toaster
30.74 Amazon 1501 2024-11-13
150 Toaster
20.33 Lidl 2461 2025-03-28

📈 Statistiken pro Spalte (vor / nach Filter)

Spalte Statistik 🔄 Vor Filter 🔍 Nach Filter
price count 150,00 150,00
price countDistinct 148,00 148,00
price sum 7.966,09 7.966,09
price avg 53,11 53,11
price min 19,20 19,20
price max 105,37 105,37
price range 86,17 86,17
price median 43,42 43,42
price mode 48,12 48,12
price variance 796,92 796,92
price stddev 28,23 28,23
stock count 150,00 150,00
stock countDistinct 147,00 147,00
stock sum 378.032,00 378.032,00
stock avg 2.520,21 2.520,21
stock min 29,00 29,00
stock max 4.996,00 4.996,00
stock range 4.967,00 4.967,00
stock median 2.534,50 2.534,50
stock mode 2.558,00 2.558,00
stock variance 2.196.468,28 2.196.468,28
stock stddev 1.482,05 1.482,05
rating count 150,00 150,00
rating countDistinct 5,00 5,00
rating sum 470,00 470,00
rating avg 3,13 3,13
rating min 1,00 1,00
rating max 5,00 5,00
rating range 4,00 4,00
rating median 3,00 3,00
rating mode 4,00 4,00
rating variance 1,83 1,83
rating stddev 1,35 1,35


<?php
$pageTitle = "JsonSQL Aggregat-Demo mit Filter";

$JsonSQLpath = __DIR__ . '/../../src/JsonSQL.php';
if (!file_exists($JsonSQLpath)) {
    die("❌ Datei nicht gefunden!");
}
require_once $JsonSQLpath;

require_once __DIR__ . '/../includes/header.php';

use Src\JsonSQL;



function fakeAggregatRow(string $product, int $id): array {
    $vendors = ['Amazon', 'MediaMarkt', 'eBay', 'Otto', 'Saturn', 'Lidl', 'Real', 'Aldi'];
    $price = match ($product) {
        'Kaffeemaschine' => rand(75, 105) + rand(0, 99) / 100,
        'Wasserkocher'   => rand(35, 55) + rand(0, 99) / 100,
        'Toaster'        => rand(19, 30) + rand(0, 99) / 100,
    };
    return [
        'id' => $id,
        'product' => $product,
        'rating' => rand(1, 5),
        'price' => round($price, 2),
        'vendor' => $vendors[array_rand($vendors)],
        'stock' => rand(0, 5000),        
        'date' => date('Y-m-d', strtotime("2024-11-01 +" . rand(0, 150) . " days"))
    ];
}

// Init
$db = new JsonSQL(['aggregat_demo' => __DIR__ . '/../testdb/aggregat_demo']);
$table = 'aggregat_demo_data';
$db->use('aggregat_demo')->setTable($table);



// Daten neu generieren, wenn "reset=1"
if (isset($_GET['reset']) && $_GET['reset'] == 1) {

// Anzahl Einträge pro Produkt holen
  $entriesPerProduct = isset($_GET['entriesPerProduct']) ? max(1, (int)$_GET['entriesPerProduct']) : 2;  

  // Tabelle leeren und neue Einträge erzeugen
  $db->truncate($table);

  $id = 1;

  $useTransaction = isset($_GET['useTransaction']);


  if ($useTransaction) {
    $db->transact();
  }

  foreach (['Kaffeemaschine', 'Wasserkocher', 'Toaster'] as $product) {
      for ($i = 0; $i < $entriesPerProduct; $i++) {
          $db->insert(fakeAggregatRow($product, $id++));
      }
  }
  if ($useTransaction) {
      $db->commit();
  }

  // Nach dem Erzeugen: Redirect, um Parameter aus URL zu entfernen
  $url = strtok($_SERVER["REQUEST_URI"], '?'); // Basis-URL ohne Parameter
  // header("Location: $url");
  // exit;  
} else {
  $db->setTable($table,true);
}  


// Filterwerte holen
$filterProduct = trim($_GET['product'] ?? '');
if ($filterProduct !== '') {
    $db->where([['product', '=', $filterProduct]]);
}
$filterVendor = trim($_GET['vendor'] ?? '');
if ($filterVendor !== '') {
    $db->where([['vendor', '=', $filterVendor]]);
}

// Daten laden und ggf. filtern
$db->select()->from($table)->get();

// Summe berechnen
$column = 'price';
$result_sum_all = $db->sum($column);
$result_avg_all = $db->avg($column);

$resultcount_all = $db->count();



$vendors = $db->distinct('vendor');
$products = $db->distinct('product');
$debugger->dump($vendors,$products);


$db->select()->from($table);
$conditions = [];

if ($filterVendor) {
    $conditions[] = ['vendor', '=', $filterVendor];
}
if ($filterProduct) {
    $conditions[] = ['product', '=', $filterProduct];
}

$debugger->addInfoText('Filter');


if (!empty($conditions)) {
   $db->where($conditions); // wirkt als OR-Verknüpfung
}

$debugger->dump($conditions,$db);



// Summe berechnen
$column = 'price';
$result_sum = $db->sum($column);
$result_avg = $db->avg($column);

$resultcount = $db->count();


$data = $db->get();
// Distinct für Dropdowns
// $vendors = $db->distinct('vendor');
// $products = $db->distinct('product');

$numericFields = ['price', 'stock', 'rating'];
$stats_all = [];
$stats_filtered = [];

$db->select()->from($table);

foreach ($numericFields as $field) {
    // Ohne Filter

    $stats_all[$field] = $db->stats($field);

    // Mit Filter

    if (!empty($conditions)) {
        $db->where($conditions);
    }
    $stats_filtered[$field] = $db->stats($field);
}




?>

<div class="container">
  <h1 class="mb-4">📊 JsonSQL Aggregat-Demo mit Filter</h1>

  <div class="mb-4">
  <p class="lead">
    Diese interaktive Demo zeigt die Möglichkeiten von <strong>JsonSQL</strong> zur Analyse strukturierter JSON-Daten – ganz ohne klassische Datenbank.
  </p>
  <p>
    Über das komfortable Filtermenü kannst du gezielt Produkte und Händler auswählen. Anschließend werden dir automatisch alle relevanten Statistiken wie <strong>Summe, Durchschnitt, Median, Minimum, Maximum, Spannweite, Varianz</strong> und <strong>Standardabweichung</strong> für numerische Felder wie Preis, Lagerbestand und Bewertung angezeigt – jeweils vor und nach dem Filter.
  </p>
  <p>
    Zusätzlich kannst du Testdaten generieren und optional den <strong>Transaktionsmodus</strong> aktivieren, um Datenänderungen gesammelt zu speichern.
  </p>
</div>

<hr>



  <form method="get" class="row g-3 mb-4">
  <input type="hidden" name="reset" value="1">

  <div class="col-md-3">
    <label for="entriesPerProduct" class="form-label">Anzahl pro Produkt:</label>
    <input type="number" class="form-control" id="entriesPerProduct" name="entriesPerProduct"
           value="<?= htmlspecialchars($_GET['entriesPerProduct'] ?? 5) ?>" min="1" max="1000">
  </div>

  <div class="col-md-3">
    <label for="useTransaction" class="form-label">Transaktionsmodus:</label>
    <div class="form-check pt-2">
      <input class="form-check-input" type="checkbox" name="useTransaction" value="1" id="useTransaction"
             <?= isset($_GET['useTransaction']) ? 'checked' : '' ?>>
      <label class="form-check-label" for="useTransaction">
        Verwenden
      </label>
    </div>
  </div>

  <div class="col-md-3 align-self-end">
    <button type="submit" class="btn btn-warning">🔁 Daten neu generieren</button>
  </div>
</form>



<hr>


  <form method="get" class="row g-3 mb-4">
    <div class="col-md-3">
      <label for="vendor" class="form-label">Händler:</label>
      <select id="vendor" name="vendor" class="form-select">
        <option value="">Alle</option>
        <?php foreach ($vendors as $v): ?>
          <option value="<?= $v ?>" <?= $v === $filterVendor ? 'selected' : '' ?>><?= $v ?></option>
        <?php endforeach; ?>
      </select>
    </div>
    <div class="col-md-3">
      <label for="product" class="form-label">Produkt:</label>
      <select id="product" name="product" class="form-select">
        <option value="">Alle</option>
        <?php foreach ($products as $p): ?>
          <option value="<?= $p ?>" <?= $p === $filterProduct ? 'selected' : '' ?>><?= $p ?></option>
        <?php endforeach; ?>
      </select>
    </div>
    <div class="col-md-6 align-self-end">
  <div class="d-flex gap-2">
    <button class="btn btn-outline-secondary" type="submit">🔍 Filtern</button>
    <a href="<?= strtok($_SERVER["REQUEST_URI"], '?') ?>" class="btn btn-outline-secondary">⏮️ Zurücksetzen</a>
  </div>
</div> 
  </form>

  <h5>📋 Datentabelle (<?= count($data) ?> Einträge)</h5>
  <?php if (!empty($data) && is_array(reset($data))): ?>
  <div class="table-wrapper mb-4">
    <table class="table table-sm table-striped table-bordered">
      <thead class="table-light">
        <tr>
          <?php foreach (array_keys(reset($data)) as $key): ?>
            <th><?= htmlspecialchars($key) ?></th>
          <?php endforeach; ?>
        </tr>
      </thead>
      <tbody>
        <?php foreach ($data as $row): ?>
          <tr>

          <?php foreach ($row as $key => $value): ?>
  <?php if ($key === 'rating'): ?>
    <?php $stars = (int) $value; ?>
    <td title="<?= $stars ?> Sterne im Rating">
      <div class="rating-stars">
        <?php
          for ($i = 0; $i < $stars; $i++) {
            echo '<i class="bi bi-star-fill text-warning"></i>';
          }
          for ($i = $stars; $i < 5; $i++) {
            echo '<i class="bi bi-star text-muted"></i>';
          }
        ?>
      </div>
    </td>
  <?php else: ?>
    <td><?= htmlspecialchars((string) $value) ?></td>
  <?php endif; ?>
<?php endforeach; ?>

          </tr>
        <?php endforeach; ?>
      </tbody>
    </table>
  </div>
<?php else: ?>
  <div class="alert alert-warning">Keine Daten gefunden für die aktuelle Auswahl.</div>
<?php endif; ?>

<?php if (!empty($column)): ?>



<h4 class="mt-5">📈 Statistiken pro Spalte (vor / nach Filter)</h4>

<div class="row">
  <div class="col-12 col-lg-8">
    <div class="stats-table-wrapper mb-5">
      <table class="table table-sm table-striped table-bordered table-hover align-middle">
        <thead class="table-light text-center">
          <tr>
            <th>Spalte</th>
            <th>Statistik</th>
            <th>🔄 Vor Filter</th>
            <th>🔍 Nach Filter</th>
          </tr>
        </thead>
        <tbody>
          <?php
          // Formatierungsfunktion
          function fmt($val): string {
              if (is_array($val)) return json_encode($val, JSON_UNESCAPED_UNICODE);
              if (is_numeric($val)) return number_format((float) $val, 2, ',', '.');
              return htmlspecialchars((string) $val);
          }
          ?>

          <?php foreach ($numericFields as $field): ?>
            <?php foreach ($stats_all[$field] as $key => $val): ?>
              <tr>
                <td><?= htmlspecialchars($field) ?></td>
                <td><?= htmlspecialchars($key) ?></td>
                <td class="text-end"><?= fmt($val) ?></td>
                <td class="text-end"><?= fmt($stats_filtered[$field][$key] ?? null) ?></td>
              </tr>
            <?php endforeach; ?>
          <?php endforeach; ?>
        </tbody>
      </table>
    </div>
  </div>
</div>





<?php 

endif;
$scriptName = basename(__FILE__);
$scriptContent = file_get_contents(__FILE__);
$scriptContent = preg_replace('//s', '', $scriptContent);
?>

<!-- Exclude Begin -->
<div class="container mt-5 mb-3">
  <hr class="shadow-lg rounded">
  <div class="accordion" id="codeAccordion">
    <div class="accordion-item">
      <h2 class="accordion-header" id="headingCode">
        <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseCode" aria-expanded="false" aria-controls="collapseCode">
          📄 Quellcodeauszug dieser Demo anzeigen (<?= htmlspecialchars($scriptName) ?>)
        </button>
      </h2>
      <div id="collapseCode" class="accordion-collapse collapse" aria-labelledby="headingCode" data-bs-parent="#codeAccordion">
        <div class="accordion-body">
          <pre class="code-block language-php"><code><?php echo htmlspecialchars($scriptContent); ?></code></pre>
        </div>
      </div>
    </div>
  </div>
</div>

<style>
.table-wrapper {
  max-height: 400px;
  overflow-y: auto;
}

.table-wrapper table {
  border-collapse: separate;
  width: 100%;
}

.table-wrapper thead th {
  position: sticky;
  top: 0;
  background: #f8f9fa;
  z-index: 2;
}

.stats-table-wrapper {
    max-height: 400px;
    overflow-y: auto;
    position: relative;
    border: 1px solid #dee2e6;
    border-radius: .375rem;
  }

  .stats-table-wrapper table {
    width: 100%;
    border-collapse: separate;
  }

  .stats-table-wrapper thead th {
    position: sticky;
    top: 0;
    background: #f8f9fa;
    z-index: 5;
    box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
  }

.rating-stars i:hover {
  color:rgb(255, 176, 7); /* bleibt golden, aber du könntest auch z. B. orange nehmen */
  text-shadow: 0 0 5px rgb(225, 101, 0);
}


</style>

</div>

<?php require_once __DIR__ . '/../includes/footer.php'; ?>