SQL-hjälp, enkel SQL-sats

Tråden skapades och har fått 9 svar. Det senaste inlägget skrevs .
1
  • Medlem
  • Stockholm
  • 2004-09-13 22:59

Håller på med ett ekonomisystem där en användare registerar kategorier och transaktioner (tillhörandes en kategori).

Nu är det som så att jag vill, dels av nyfikenhet, skriva en SQL-sats som tar fram statistik så jag kan kladda upp lite HTML som berättar hur mycket man gjort av med per kategori och månad (och år).

En transaktion innehåller bland annat
-en ägare (heltal, pekar ut en ur users-tabellen)
-ett 'amount' dvs antal kronor som transaktionen är på
-en kategori som transaktionen ska grupperas under (heltal, pekar ut en ur categories-tabellen)
-ett datum som säger när transaktionen gjordes (performed)

Vad SQL-frågan ska ta fram är (grupperat per månad och år)
- inkomster, utgifter för varje kategori.

Lite kriterier:
- Om inga utgifter eller inkomster finns för en kategori så behöver den kategorin inte visas
- Om utgifter finns men inte inkomster så ska inkomster innehålla värdet 0 (och vice versa)

I dagsläget har jag 3st selectsatser som jag alltså vill slå ihop till en.

Denna tar fram summan av samtliga utgifter, grupperat efter år och månad

$sql_1 = "
SELECT
  SUM(ABS(t." . TABLE_TRANSACTIONS_AMOUNT . ")) AS total,
  YEAR(FROM_UNIXTIME(t."	. TABLE_TRANSACTIONS_PERFORMED . ", '%Y-%m-%d')) AS year,
  MONTH(FROM_UNIXTIME(t."	. TABLE_TRANSACTIONS_PERFORMED . ", '%Y-%m-%d')) AS month,
  t." . TABLE_TRANSACTIONS_PERFORMED . "
FROM
  " . TABLE_TRANSACTIONS . " t
WHERE
  t." . TABLE_TRANSACTIONS_OWNER . " = '" . $user_id . "'
 AND (t." . TABLE_TRANSACTIONS_AMOUNT . " < 0 )	
GROUP BY
  year DESC, month DESC
";

Den här körs för varje rad som hämtats i frågan åvan.
Den hämtar hem antalet transaktioner gjorda per kategori samt summerar hur mycket utgifter just den kategorin stod för den månaden (och året).

$sql_2="
SELECT
  c." . TABLE_CATEGORIES_TITLE . ", c.id,
  SUM(ABS(t." . TABLE_TRANSACTIONS_AMOUNT . ")) AS total,
  COUNT(*) AS num
FROM
  " . TABLE_TRANSACTIONS . " t,
  " . TABLE_CATEGORIES . " c
WHERE
  t." . TABLE_TRANSACTIONS_OWNER . " = '" . $user_id . "'
 AND YEAR(FROM_UNIXTIME(t."	. TABLE_TRANSACTIONS_PERFORMED . ", '%Y-%m-%d')) = " . $year . "
 AND MONTH(FROM_UNIXTIME(t."	. TABLE_TRANSACTIONS_PERFORMED . ", '%Y-%m-%d')) = " . $month . "
 AND (t.amount < 0 )
 AND c.id = t.category_id
GROUP BY c." . TABLE_CATEGORIES_TITLE . "
";

Sedan kommer en likadan 3dje SQL-sats fast med skillnaden att den hämtar inkomsterna för kategorierna.

HTML-koden blir väldigt mycket lättare att kladda upp om all datat finns direkt på samma rad i resultatet.

Dessutom, vilket är bäst: Att skicka 4-5st förfrågningar till databasen eller skriva en lite tyngre select-sats?? Jag försöker designa systemet för större skala, säg flera hundra användare samtidigt.

mvh
ivar

Senast redigerat 2004-09-16 16:41

Jahapp... Vad vill du ha hjälp med, egentligen?

Även om jag inte är säker på att jag kan hjälpa dig blir det också mycket enklare om du postar lite information om tabellerna, och SQL-erna utan PHP-kod.

  • Medlem
  • Stockholm
  • 2004-09-14 11:17

Hehehe... jag vill ha hjälp med att skriva EN enda SQL-fråga som gör att jag kan skriva ut en tabell, se kod.

SQL-frågan skall gruppera resultatet efter månad och år och varje rad ska innehålla kategorinamn, kategori_id och summan av utgifter(och inkomster) för den kategorin.

<table>
<tr>
  <th>Kategori</th>
  <th>Inkomster</th>
  <th>Utgifter</th>
  <th>Totalt</th>
</tr>
<?php

//Här skrivs den komplicerade SQL-frågan 

// Hjälp variabler för att få totala summan för alla kategorierna
$total_expenses = 0;
$total_incomes = 0;

// loopa igenom resultatet
while( $data = mysql_fetch_array($result) ) {
$total_expenses = $total_expenses + $data['expenses'];
$total_incomes = $total_incomes + $data['incomes'];
?>
<tr>
  <td><?php echo $data['category_name']; ?></td>
  <td><?php echo $data['incomes']; ?></td>
  <td><?php echo $data['expenses'];?></td>
  <td><?php echo ($data['incomes'] - $data['expenses']);</td>
</tr>
<?php
}
?>
<tr>
  <td>Totalt</td>
  <td><?php echo $total_incomes; ?></td>
  <td><?php echo $total_expenses; ?></td>
  <td><?php echo ($total_incomes - $total_expenses); ?></td>
</tr>
</table>

Här kommer tabellerna i fråga.. tänkte att de definierade konstanterna kanske räckte för att bygga upp SQL-frågan men strunt samma
Alla förslag på hur dessa tabeller kan förbättras är varmt välkomna!

# Dump of table categories
# ------------------------------------------------------------

CREATE TABLE `categories` (
`id` int(3) NOT NULL auto_increment,
`owner_id` int(3) NOT NULL default '-1',
`title` varchar(50) default NULL,
`description` text,
`date_created` int(10) default NULL,
`date_modified` int(10) default NULL,
PRIMARY KEY (`id`)
) TYPE=MyISAM COMMENT='Alla anvŠndarnas skapta kategorier.';

# Dump of table transactions
# ------------------------------------------------------------

CREATE TABLE `transactions` (
`id` int(11) NOT NULL auto_increment,
`owner_id` int(3) NOT NULL default '0',
`category_id` int(3) default NULL,
`amount` decimal(8,2) NOT NULL default '0.00',
`comment` text,
`date_created` int(10) default NULL,
`date_performed` int(10) default NULL,
`date_modified` int(10) default NULL,
PRIMARY KEY (`id`)
) TYPE=MyISAM;

# Dump of table users
# ------------------------------------------------------------

CREATE TABLE `users` (
`user_id` int(3) NOT NULL auto_increment,
`un` varchar(10) NOT NULL default 'demo',
`pw` varchar(40) NOT NULL default 'demo',
`name` varchar(20) default NULL,
PRIMARY KEY (`user_id`)
) TYPE=MyISAM;

  • Medlem
  • Stockholm
  • 2004-09-15 00:45

Ok, vi gör det riktigt enkelt.

Ni har de tre tabellerna åvan (categories, users & transactions) och jag vill skriva en sql-fråga som för varje rad innehåller
1. datum
2. summa utgifter för en kategori
3. summa inkomster för en kategori
sen så loopar man igenom raderna så man får fram alla kategoriers utgifter och inkomster.

mer detaljerat så ska en resultat-rad innehålla
owner_id: 1 (vilken user transaktionerna tillhör)
date: 134892349 (typ, unix-timestamp där man kan få fram månad och år)
category_id: 33
category_name: Telefon
total_incomes_this_month: 3500
total_expenses_this_month: 1200

capishe? (felstavat va?)

  • Medlem
  • 2004-09-15 01:19

Na't i den har stilen borde funka. Du kanske far mecka lite med datumet for att det skall fungera. Utan att veta hur du anvander dina tabeller sa ser de lite ineffektiva ut. Du borde kunna rensa lite behovs t.ex. owner_id i Categories?

SQL
Select
u.user_id as User,
to_char(t.date_created, 'mon-YY') as Date,
t.category_id as Category,
c.title as Category_Name,
sum(case when t.amount > 0 then t.amount) as total_revenue_this_month,
sum(case when t.amount < 0 then t.amount) as total_outlays_this_month
FROM
categories c,
transactions t,
users u
WHERE
t.owner_id = u.user_id, -- Antar att detta ar samma falt
t.category_id = c.id
GROUP BY
u.user_id, to_char(t.date_created, 'mon-YY'), t.category_id, c.title

Nu grupperas allt pe user_id sa det kommer bli en fasligt massa rader. Som ett summary sa vill du formodligen gruppera per kategori och datum. Dvs. GROUP BY t.category_id, c.title, to_char(t.date_created, 'mon-YY' (user_id tar du bort helt)

Lycka till!

Ursprungligen av ivar:

Ok, vi gör det riktigt enkelt.

Ni har de tre tabellerna åvan (categories, users & transactions) och jag vill skriva en sql-fråga som för varje rad innehåller
1. datum
2. summa utgifter för en kategori
3. summa inkomster för en kategori
sen så loopar man igenom raderna så man får fram alla kategoriers utgifter och inkomster.

mer detaljerat så ska en resultat-rad innehålla
owner_id: 1 (vilken user transaktionerna tillhör)
date: 134892349 (typ, unix-timestamp där man kan få fram månad och år)
category_id: 33
category_name: Telefon
total_incomes_this_month: 3500
total_expenses_this_month: 1200

capishe? (felstavat va?)

  • Medlem
  • Stockholm
  • 2004-09-15 09:04

Hinner inte prova exakt nu men det ser ju bra ut!

Tror inte tabellerna är ineffektiva.
En användare skapar kategorier och transaktioner.. ingen annan användare ska se andras transaktioner och kategorier... därför krävs nog owner_id i categories.

  • Medlem
  • Stockholm
  • 2004-09-15 21:10
Ursprungligen av ivar:

Tror inte tabellerna är ineffektiva.

Bara att kolla med normalformerna annars.

  • Medlem
  • 2004-09-15 21:03

ok, i sa fall far du koppla ihop owner_id pa categories and transactions ocksa under WHERE.

  • Medlem
  • Stockholm
  • 2004-09-15 22:48

Jag svarade "tror" för att vara lite ödmjuk.

Men det verkade ju iof mer vara en fråga om att 'Oops' inte visste att en kategori ska tillhöra en user, och således ha en 'owner_id'-kolumn.

  • Medlem
  • Stockholm
  • 2004-09-16 16:36

Okej!

Har lyckats få till den nu (nästan då)

SELECT
	CASE WHEN (t.amount < 0) THEN
		SUM(t.amount)
	END AS expense,
	CASE WHEN (t.amount > 0) THEN
		SUM(ABS(t.amount))
	END AS income,
	YEAR(FROM_UNIXTIME(t.date_performed, '%Y-%m-%d')) AS year,
	MONTH(FROM_UNIXTIME(t.date_performed, '%Y-%m-%d')) AS month,
	c.title AS category
FROM
	transactions t, categories c
WHERE
	t.owner_id  = $user_id
	AND t.category_id = c.id
GROUP BY
	year DESC, month DESC, category

Verkade fungera hur bra som helst tills jag hittade att case-satserna inte fungerar till 100%
Problemet verkar vara att den bestämmer sig för att summera som expense eller income beroende på den första transaktionen den hittar inom just den kategorin...

1
Bevaka tråden