Vous n'êtes pas identifié(e).

#101 PL/pgSQL » RESOLU - utilisation d'un curseur » 03/03/2013 08:56:19

damalaan
Réponses : 6

Bonjour,

Pour m'apprendre à utiliser le PL/pgSQL, j'ai écrit cette fonction (qui présente peu d'intérêt en soi !) : le but est de parcourir la table tbl_analyse_ana et de récupérer le ana_id de chaque ligne puis de concaténer le résultat dans une variable de manière à avoir en sortie qqc du genre 1;2;3;4;5 etc.
Mais j'ai du louper qqc car la fonction ne génère pas d'erreur mais ne retourne rien

-- Function: test()

CREATE OR REPLACE FUNCTION test()
  RETURNS TEXT AS
$BODY$
DECLARE
s RECORD;
s1 TEXT;
cur CURSOR FOR SELECT ana_id FROM tbl_analyse_ana;
BEGIN
open cur;
LOOP
FETCH cur INTO s;
s1 := s1 || ';' || s.ana_id || ';';


END LOOP;
CLOSE cur;
RETURN s1;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION test()
  OWNER TO postgres;

merci de votre aide

#102 Re : Général » formatage de champ » 27/02/2013 17:20:19

je viens de faire ça

CASE imp_germes
	WHEN '' THEN null
	ELSE imp_germes
	END::integer as imp_germes

et ça marche
donc WHEN null THEN null génère une erreur
et WHEN '' THEN null fonctionne !?

merci de votre aide

#103 Re : Général » formatage de champ » 27/02/2013 17:11:57

les moufles c'est normal, il fait froid :-)

un exemple :
données avant formatage (type text)
10
   <----
21
12
10

après formatage (type integer)
10
-1 <----
21
12
10

donc le vide prend la valeur de -1 alors qu'il doit rester vide.
je pense faire 2ème  requete où je vais formater comme ça :

CASE imp_germes
WHEN -1 then null
ELSE imp_germes
END

#104 Re : Général » formatage de champ » 27/02/2013 16:40:27

mais du coup les null qui doivent rester null ne sont plus null !!??

#105 Général » formatage de champ » 27/02/2013 16:32:18

damalaan
Réponses : 7

Bonjour

Suite à un import de fichier, je formate mes champs et j'ai un souci sur un champ qui au départ est en texte (et qui doit devenir entier) avec des lignes vides et d'autre avec des nombres.
extrait de ma requête :

CASE imp_germes
	WHEN  null THEN null
	ELSE imp_germes::integer
END

ERREUR:  syntaxe en entrée invalide pour l'entier : «  »

********** Erreur **********

ERREUR: syntaxe en entrée invalide pour l'entier : «  »
État SQL :22P02

j'ai testé sur un champ où je suis sûr qu'il n'y a pas de ligne vide et celà fonctionne.

Merci de votre aide

#106 Re : Général » classement avec rattrapage » 05/12/2012 14:42:08

Je me réponds à moi même , non pas que j'ai trouvé la solution hélas mais pour corriger une erreur dans le jeu de donnée en exemple
Concernant les 9 dernières valeurs (sur mars avril et mai), pour que mon exemple fonctionne je remplace le 1334 du 07/03 par 1247.

Voici un exemple de données avec une seuil fixe à 1250

ligne     produit       date                  defaut     moy             classement
ligneA    993001    07/02/11 00:00    1710        
ligneA    993001    18/02/11 00:00    1687        
ligneA    993001    23/02/11 00:00    1249    1533.055498    B

ligneA    993001    07/03/11 00:00    1247       
ligneA    993001    18/03/11 00:00    728        
ligneA    993001    23/03/11 00:00    954    966.1131897    A

ligneA    993001    06/04/11 00:00    856        
ligneA    993001    15/04/11 00:00    1005        
ligneA    993001    27/04/11 00:00    934    929.6701802    A

ligneA    993001    04/05/11 00:00    974        
ligneA    993001    13/05/11 00:00    989        
ligneA    993001    26/05/11 00:00    1111    1022.876268    A

ligneA    993001    07/06/11 00:00    1167        
ligneA    993001    13/06/11 00:00    1212        
ligneA    993001    29/06/11 00:00    1400    1255.742242    B==>A

A chaque fois que je calcule une moyenne (avec un group by sur ligne, produit, mois), j'établis un premier classement avec une instruction case when==> ça je gère!

ensuite, il faut que j'aille compter le nombre de fois ou le produit x sur la ligne y a plus de 1250 defauts relevés sur les 9 derniers comptages précédent le mois "moyenné" (donc sur les 3 mois auparavant pour faire plus simple). Et si ce comptage est = 0, alors je peux rattraper le classement et le remonter d'un cran.

Est-ce plus clair ainsi?

#107 Général » classement avec rattrapage » 24/11/2012 21:54:37

damalaan
Réponses : 1

Bonjour,

J'ai le code suivant qui me renvoie un classement de produit en fonction d'une moyenne
représentant le nombre de defaut

with
moy as (select res_ligne, res_prod, to_char(res_date, 'YYYYMM') as mois, exp(avg(ln(res_defaut))) as moy_geo
 from tbl_resultat_res
 group by res_ligne, res_prod, to_char(res_date, 'YYYYMM')),
 class as(
 select res_ligne, res_prod, mois, moy_geo,
 case
 when moy_geo <=1250 then 'A'
 when moy_geo > 1250 and moy_geo <= 1500 then 'B'
 when moy_geo > 1500 and moy_geo <= 1750 then 'C'
 when moy_geo > 1750 and moy_geo <= 2000 then 'D'
 else 'E'
 end as class
 from moy)
 select * from class
 ;
 

maintenant je voudrais introduire un système de rattrapage du genre :
soit :  si un produit est classé en B C D ou E et si sur les 3 derniers mois 7 comptages de defaut sur 9
sont inférieur à 1250 alors je le surclasse c'est à dire que qu'un B je le passe en A, un C en B, etc

soit je prends comme seuil de rattrapage glissant :
pour passer de B en A ==>7 résultats <=1250
de C en B ==> 7 résultats <=1500
de D en C==> 7 résultats <=1750
de E en D ==> 7 résultats <= 2000

je ne me suis pas encore décidé sur le mode de rattrapage, mais là je bloque sur les 2!

Voici un exemple de données avec une seuil fixe à 1250
ligne     produit       date                  defaut     moy             classement
ligneA    993001    07/02/11 00:00    1710       
ligneA    993001    18/02/11 00:00    1687       
ligneA    993001    23/02/11 00:00    1249    1533.055498    B
ligneA    993001    07/03/11 00:00    1334       
ligneA    993001    18/03/11 00:00    728       
ligneA    993001    23/03/11 00:00    954    974.8666074    A
ligneA    993001    06/04/11 00:00    856       
ligneA    993001    15/04/11 00:00    1005       
ligneA    993001    27/04/11 00:00    934    929.6701802    A
ligneA    993001    04/05/11 00:00    974       
ligneA    993001    13/05/11 00:00    989       
ligneA    993001    26/05/11 00:00    1111    1022.876268    A
ligneA    993001    07/06/11 00:00    1167       
ligneA    993001    13/06/11 00:00    1212       
ligneA    993001    29/06/11 00:00    1400    1255.742242    B==>A


le dernier est rattrapable car sa moyenne est supérieure au seuil, mais sur les 9 resultats de comptage des mois précedent le calcul de la moyenne, aucun n'est supérieure à 1250

#108 Re : Général » comptage de valeurs consécutives » 12/11/2012 21:44:10

Je pense que je passerais par les fonctions de fenêtrage et notamment les fonctions lag ou lead pour comparer les lignes entre elles


pour la syntaxe exacte, regardez la doc, car comme ça j'aurais du mal à vous donner un code correct!

http://docs.postgresqlfr.org/9.1/functions-window.html

#109 Re : Général » Problème de connexion » 08/10/2012 11:51:12

Il me semble que cela m'est déjà arrivé sur un portable équiper de windows7.
Et je crois que la solution est de mettre le répertoire data ailleurs que dans le Program Files (à l'installation): apparemment c'est l'espace du program files qui pourrait parfois poser problème
Je ne sais plus où j'avais trouver l'astuce l'info :-(

#110 Re : Général » Calcul de moyenne sur 2 mois » 13/09/2012 09:45:16

merci jpargudo pour cette démo!
je n'ai pas opté pour votre solution

Je crée dans une requête le mois de "référence" de cette manière, et après je l'utilise pour mon regroupement

Pardon pour la trituration de la date, mais elle est stockée d'une manière particulière qui m'oblige à faire des imbrications de fonction pour en retirer qqc (cf la plupart de mes posts sur ce forum!!)

	CASE extract(month from (to_timestamp((tbl_tournee_trn.trn_date_prel / 100)::text, 'YYMM'::text)))::integer%2
	WHEN 0 THEN to_timestamp((tbl_tournee_trn.trn_date_prel / 100)::text, 'YYMM'::text)+ '1 month'::interval
	WHEN 1 THEN to_timestamp((tbl_tournee_trn.trn_date_prel / 100)::text, 'YYMM'::text)
	END as mois_ref

j'extrais le mois, un modulo 2 pour voir s'il est pair ou impair;
si pair, j'ajoute 1 mois
si impair je garde le même mois

celà me semble plus simple!

#111 Général » Calcul de moyenne sur 2 mois » 12/09/2012 11:27:27

damalaan
Réponses : 4

Bonjour,

Il faut que je calcule une moyenne en faisant un regroupement sur un champ de type date mais la particularité est que le calcul doit se faire au bimestre (2mois, le 2ème mois étant toujours impair).
Par exemple, il me faut calculer la moyenne pour Décembre 2011 et Janvier 2012, puis Février et Mars 2012, Avril et Mai 2012, etc.
Vu  ce regroupement un peu particulier, je n’arrive à voir comment faire !

Merci d’avance

#112 Re : Général » problème de connexion ODBC » 06/09/2012 13:16:47

je me reponds à moi même, la pause déjeuner m'ayant été bénéfique!!

finalement c'est bien un problème d'ip : dans la chaine ODBC, l'ip est présente
j'ai donc modifié la connexion odbc en localhost, lié de nouveau toutes les tables et vues nécessaires dans le fichier Access avec cette nouvelle connexion ODBC et ça fonctionne!

#113 Général » problème de connexion ODBC » 06/09/2012 12:29:07

damalaan
Réponses : 4

Bonjour

j'ai installé une base Postgres sur un portable pour faire une démo en réunion.
comme l'UI tourne sous Access, il faut aussi configurer une connexion ODBC.
j'ai attribué la même adresse ip au portable quelle celle du serveur ou tourne postgres pour ne pas avoir à refaire l'UI, sauf que ça ne fontionne pas:
je configure ma connexion ODBC via les outils d'administations de windows et quand je teste la connexion cela marche en "localhost" mais pas avec l'ip 192.168.1.64!!
j'ai modifié les fichiers pg_hba.conf

host	 Indext	 		all	 			192.168.0.0/0		    md5

comme le portable n'est pas connecté à aucun réseau, je pense que ça vient de là! quand je fais un ipconfig, il ne me renvoie pas d'adresse ip

merci d'avance

#114 Re : Optimisation » Recherche d'optimisation sur calcul de requete » 17/08/2012 08:28:58

NICKEL!!!

Avec le même volume de données (soit plus de 530 000 lignes), je gagne 20s d'exécution (je passe de 36s à 17s)
Tout en sachant que je ne travaille la plupart du temps que sur 50 000 à 70 000 lignes, la requête finale prend alors moins d'1s. cool

Avec tous mes remerciements !

#115 Re : Optimisation » Recherche d'optimisation sur calcul de requete » 16/08/2012 16:25:52

je suis bien d'accord que supprimer des requêtes puis les recréer n'est pas très ....pro

Le principe que j'ai actuellement :
R1 : calcul des écarts entre les valeurs d'une même colonne en utilisant une fonction WINDOW
R2 : calcul à partir de l'écart calculé en R1 un écart type, avec un regroupement sur 4 colonnes (espèce, usine, tournée, mois)
R3 : calcul à partir de  l'écart-type calculé en R2, la moyenne des écart types avec un regroupement sur 2 colonnes (espèce, mois)
R4 : comparaison des écart types obtenus en R2 avec la moyenne R3 pour définir des alertes
R5 : comparaison des alertes identifiées en R4 sur 2 mois consécutifs, afin d'identifier la récurrence éventuelle d'apparition des alertes

J'ai commencé à essayer de rassembler tous mes requêtes en 1 seule mais ça devient rapidement compliqué! J'en suis resté à R2!

J'imagine donc qu'il va falloir que je poursuive mon idée en PL/pgSQL. Est-il possible de créer un genre de requête temporaire en PL/pgSQL? (et est-ce une bonne idée?)

#116 Re : Optimisation » Recherche d'optimisation sur calcul de requete » 10/08/2012 08:12:50

Je crois n'avoir pas bien compris le Explain : effectivement je suis à 2.5s d'exécution après les modifs d'index et de mémoire.
mais le select en lui même n'a pas tellement changé : pg Admin renvoie

Je voudrais donc poursuivre sur mon idée d'hier de n'utiliser que les éléments nécessaires et non toute une table.

Faut-il que je crée une fonction qui fasse toutes requêtes d'un seul coup en les supprimant et recréant à chaque fois?

#117 Re : Optimisation » Recherche d'optimisation sur calcul de requete » 09/08/2012 16:33:47

Oui mais au global ça dure toujours une trentaine de sec!

Je pense à autre chose : cette fameuse vue me sert à 4 autres en cascade(la vue 1 sert à la vue2, la vue 2 sert à la vue 3 etc), et dès la première je renvoie 500000lignes avec le

WHERE tbl_tournee_trn.trn_date_prel > 100000

Or je n'ai que très rarement besoin de travailler sur tout ça. Il me faut juste des stats sur 3 mois, donc par exemple pour Aout 2012, il faudrait que je récupère juste les données depuis juin 2012

il me faudrait qqc du genre

WHERE to_timestamp(tbl_tournee_trn.trn_date_prel/100, 'yymm') between Moncritère and Moncritère-'3 Month'::interval)

Il faudrait que je puisse paramétrer ce critère à chaque fois,.............ce que je ne sais pas faire

et pour avoir tester 'à la main', j'en suis à 2 à 3s d'exécution ce qui nickel pour l'utilisateur

#118 Re : Général » requête avec where sur année et mois d'un timestamp » 08/08/2012 15:15:42

Bizarre d'avoir une date sur une colonne appelée mois : c'est une "fausse" date car il n'y a que le mois et l'année qui m'intéresse, le jour est toujours à 1
Mais comme suggéré par Marc Cousin dans une réponse à un de mes posts précédents, il est plus simple de faire des calculs :
dans la table de départ, le mois est stocké sous forme numérique du genre 1208, mais cela pose problème pour faire des calcul du genre 1201 - 1mois; je l'ai donc passé en timestamp (mais je n'ai pas changé le nom!)

Passé de

        EXTRACT(YEAR FROM B.mois) = EXTRACT(YEAR FROM A.mois)
	AND
	EXTRACT(MONTH FROM B.mois) = EXTRACT(MONTH FROM A.mois)

à

to_char(B.mois, 'YYYYMM') = to_char(A.mois, 'YYYYMM')

est tout de même un peu plus simple!

merci

#119 Général » requête avec where sur année et mois d'un timestamp » 08/08/2012 11:30:54

damalaan
Réponses : 2

Bonjour,

J'ai la requête suivante

 SELECT 
	A.trn_esp, 
	A.trn_tournee, 
	A.trn_usine, 	
	B.mois, 
	A."EtTournee",
	B."MoyLabo"*2 as Indicateur, 
        CASE
            WHEN A."EtTournee" > (2::numeric * B."MoyLabo") THEN 'Alerte'::text
            ELSE 'ok'::text
        END AS "Alerte"
   FROM 
	"vw_simuMoisMoyLabo" B, 
	"vw_simuMoisEtTournee" A
  WHERE 
	(
	B.trn_esp = A.trn_esp 
	AND 
	(
	EXTRACT(YEAR FROM B.mois) = EXTRACT(YEAR FROM A.mois)
	AND
	EXTRACT(MONTH FROM B.mois) = EXTRACT(MONTH FROM A.mois)
	)
	)
  ORDER BY trn_esp, "Alerte";

Je voudrais savoir si ce que j'ai fait sur le WHERE est judicieux ou non.
Y a t il un autre moyen de dire : je veux les lignes des tables A et B en faisant une jointure sur le mois et l'année d'un timestamp?

#120 Re : Optimisation » Recherche d'optimisation sur calcul de requete » 08/08/2012 11:20:23

Effectivement en plaçant un index sur la colonne trn_date_prel, et en augmentant la mémoire (50MB), je gagne pas grand chose :  1 à 2 s.

Merci pour ces infos.

#121 Re : Optimisation » Recherche d'optimisation sur calcul de requete » 03/08/2012 15:17:08

taille table tbl_tournee_trn : Lignes estimées    73145   
taille table tbl_valeur_mg : Lignes estimées    650283   

voilà pour le explain

"WindowAgg  (cost=130671.82..151806.02 rows=650283 width=32) (actual time=2739.974..4027.162 rows=496831 loops=1)"
"  ->  Sort  (cost=130671.82..132297.53 rows=650283 width=32) (actual time=2739.920..3132.560 rows=496831 loops=1)"
"        Sort Key: tbl_valeur_mg.mg_matricule, tbl_tournee_trn.trn_esp, tbl_tournee_trn.trn_date_prel"
"        Sort Method:  external merge  Disk: 19624kB"
"        ->  Hash Join  (cost=2787.50..36762.70 rows=650283 width=32) (actual time=181.034..1570.746 rows=496831 loops=1)"
"              Hash Cond: (tbl_valeur_mg.trn_id = tbl_tournee_trn.trn_id)"
"              ->  Seq Scan on tbl_valeur_mg  (cost=0.00..11284.83 rows=650283 width=20) (actual time=0.052..238.358 rows=650283 loops=1)"
"              ->  Hash  (cost=1551.74..1551.74 rows=63901 width=28) (actual time=58.872..58.872 rows=62807 loops=1)"
"                    Buckets: 2048  Batches: 4  Memory Usage: 794kB"
"                    ->  Seq Scan on tbl_tournee_trn  (cost=0.00..1551.74 rows=63901 width=28) (actual time=2.371..28.166 rows=62807 loops=1)"
"                          Filter: (trn_date_prel > 100000)"
"Total runtime: 4120.821 ms"

#122 Optimisation » Recherche d'optimisation sur calcul de requete » 03/08/2012 14:51:47

damalaan
Réponses : 13

Bonjour

j'ai la requete suivante basée sur 2 table (en 1-n) dont la structure est également ci-dessous
la requête :

CREATE OR REPLACE VIEW view_ecart AS 
 SELECT tbl_tournee_trn.trn_esp, tbl_tournee_trn.trn_date_prel, tbl_tournee_trn.trn_tournee, tbl_tournee_trn.trn_chauffeur, tbl_tournee_trn.trn_usine, tbl_valeur_mg.mg_matricule, tbl_valeur_mg.mg_val, 
        CASE lag(tbl_valeur_mg.mg_val, 1) OVER (PARTITION BY tbl_valeur_mg.mg_matricule ORDER BY tbl_tournee_trn.trn_esp, tbl_tournee_trn.trn_date_prel)
            WHEN 0 THEN NULL::numeric
            ELSE 
            CASE tbl_valeur_mg.mg_val
                WHEN 0 THEN NULL::numeric
                ELSE tbl_valeur_mg.mg_val - lag(tbl_valeur_mg.mg_val, 1) OVER (PARTITION BY tbl_valeur_mg.mg_matricule ORDER BY tbl_tournee_trn.trn_esp, tbl_tournee_trn.trn_date_prel)
            END
        END AS ecart
   FROM tbl_valeur_mg
   JOIN tbl_tournee_trn USING (trn_id)
  WHERE tbl_tournee_trn.trn_date_prel > 100000;

ALTER TABLE view_ecart OWNER TO postgres;

table du coté 1:

CREATE TABLE tbl_tournee_trn
(
  trn_date_prel integer NOT NULL,
  trn_esp integer NOT NULL,
  trn_tournee integer NOT NULL,
  trn_usine integer NOT NULL,
  trn_id bigserial NOT NULL,
  trn_chauffeur integer,
  CONSTRAINT "clé_primaire" PRIMARY KEY (trn_id),
  CONSTRAINT "clé_2" UNIQUE (trn_date_prel, trn_esp, trn_tournee, trn_usine)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE tbl_tournee_trn OWNER TO postgres;

table du coté n

CREATE TABLE tbl_valeur_mg
(
  mg_id bigserial NOT NULL,
  trn_id bigserial NOT NULL,
  mg_matricule integer NOT NULL,
  mg_val numeric(4,1) NOT NULL,
  CONSTRAINT pk PRIMARY KEY (mg_id),
  CONSTRAINT fk FOREIGN KEY (trn_id)
      REFERENCES tbl_tournee_trn (trn_id) MATCH FULL
      ON UPDATE CASCADE ON DELETE CASCADE
)
WITH (
  OIDS=FALSE
);
ALTER TABLE tbl_valeur_mg OWNER TO postgres;

-- Index: index_mg

-- DROP INDEX index_mg;

CREATE INDEX index_mg
  ON tbl_valeur_mg
  USING btree
  (trn_id, mg_matricule);

Il y a un index de positionner, mais l'est-il bien?
la requete met une 30aine de seconde pour renvoyer 500000 lignes

je fais souvent appel à cette requête car je travaille beaucoup sur le calcul qui en est issu et je recherche un moyen d'augmenter un peu la rapidité

merci d'avance

#123 Re : Général » histoire de count » 25/06/2012 14:30:40

Finalement, j'ai opté pou ça :

 select count(*) from 
(
select t1.usine from tbl_test_tst t1 inner join tbl_test_tst t2
on t1.usine = t2.usine
WHERE t1.esp=1 and t2.esp =2
) as t;

et j'obtiens bien 1 (1 usine a esp=1 et esp = 2)

La table que j'ai présenté était pour l'exemple, en réalité, j'ai une jointure dès le début, ce qui me donne un truc du genre :

SELECT COUNT(*) FROM 
	(SELECT DISTINCT ta.chf_id, ta.trn_esp 
		FROM 
			(SELECT DISTINCT chf_id, trn_esp 
				FROM 
				tbl_chauffeur_chf t1 INNER JOIN tbl_tournee_trn t2
				ON t1.chf_id = t2.trn_chauffeur
				WHERE trn_date_prel >110400 AND chf_archive = FALSE) ta 
		
			INNER JOIN
		
			(SELECT DISTINCT chf_id, trn_esp 
				FROM 
				tbl_chauffeur_chf t1 INNER JOIN tbl_tournee_trn t2
				ON t1.chf_id = t2.trn_chauffeur
				WHERE trn_date_prel >110400 and chf_archive = FALSE) tb 

			ON ta.chf_id = tb.chf_id

		WHERE ta.trn_esp = 1 and tb.trn_esp=2
	) t;

Le but étant de savoir quel chauffeur a tourné sur trn_esp = 1 ET trn_esp=2

Si vous avez plus simple, je suis preneur!

#124 Re : Général » histoire de count » 21/06/2012 14:21:01

leTrucPasCompris est :
le nombre d'usine ayant comme 1 et 2  dans la colonne esp

dans ma minitable (en réel, j'ai qq centaines de lignes!), je n'ai qu'une usine ayant 1 et 2

je peux reformuler différemment pour éviter la confusion avec cette forme::
1621;b
1621;a
1622;a
1623;a
1624;b

combien y a t il d'usine ayant a ET b, réponse 1

#125 Général » Calculer une fréquence » 21/06/2012 13:48:44

damalaan
Réponses : 1

Soit  les valeurs suivantes :

id1;id2;matricule;valeur
293469;19659;11253;39.9
Pour ceux qui connaissent Excel, je cherche à reproduire la fonction matricielle Fréquence(matrice_valeurs;matrice_intervalles)

293470;19659;13207;42.5
293471;19659;5026;37.2
293472;19659;11190;44.5
293473;19659;10460;50.7
293474;19659;11107;45.4
293475;19659;15868;42.2
293476;19659;5084;45.3
293477;19659;5041;46.1

il me faut récupérer le nombre de valeurs par tranches suivantes:

39
40
41
42
43
44
45

pour avoir un résultat :

39	1
40	1
41	0
42	0
43	2
44	0
45	1

ce qui signifie que j'ai une valeur <= à 39, 1 entre dans l'intervalle ]39-40], 0 dans ]40-41] etc jusqu'à 1 dans ]44,45]

pour la partie intervalle, je pense utiliser qqc du genre
select * from generate_series(39,45,1);

Pied de page des forums

Propulsé par FluxBB