Catégorisation des commandes en utilisant SQL

The following code changes the order of categories to be alphanumeric using SQL.

Preconditions.
Postgres backend

UPDATE categories
SET POSITION = subquery.position
FROM (
	SELECT POSITION
	, CASE WHEN category_id = 0 THEN parent_category_id ELSE category_id END category_id 
	, CASE WHEN category_id = 0 THEN parent_category_name ELSE category_name END category_name 
	FROM (
		SELECT ROW_NUMBER - 1 AS POSITION
		, parent_category_id
		, parent_category_name
		, category_id
		, category_name
		FROM ( SELECT row_number() OVER ( ORDER BY parent_category_name, category_name )
		, * FROM (
		SELECT * FROM (
			SELECT id parent_category_id
			, name parent_category_name 
			, 0 category_id
			, cast('' AS text) category_name
			FROM categories 
			WHERE parent_category_id IS NULL ORDER BY name
		) parent_categories
		UNION 
		(
			SELECT child.parent_category_id
			, parent.name parent_category_name 
			, child.id category_id
			, child.name category_name
			FROM categories child
			INNER JOIN categories parent
			ON child.parent_category_id = parent.id
			WHERE child.parent_category_id IS NOT NULL ORDER BY child.name
		) 
		) parents_with_children
		ORDER BY parent_category_name, category_name
		) ordered_parents_with_children
		ORDER BY ROW_NUMBER
	) category_positions_sorted_alphabetically
) subquery
WHERE id = subquery.category_id ;

I ran the code by starting up a psql session.

/var/discourse/launcher enter app
su postgres
psql discourse

and then executing the SQL.

Running from rails console.

ActiveRecord::Base.connection.execute("UPDATE categories SET POSITION = subquery.position FROM ( SELECT POSITION , CASE WHEN category_id = 0 THEN parent_category_id ELSE category_id END category_id , CASE WHEN category_id = 0 THEN parent_category_name ELSE category_name END category_name FROM ( SELECT ROW_NUMBER - 1 AS POSITION , parent_category_id , parent_category_name , category_id , category_name FROM ( SELECT row_number() OVER ( ORDER BY parent_category_name, category_name ) , * FROM ( SELECT * FROM ( SELECT id parent_category_id , name parent_category_name , 0 category_id , cast('' AS text) category_name FROM categories WHERE parent_category_id IS NULL ORDER BY name ) parent_categories UNION ( SELECT child.parent_category_id , parent.name parent_category_name , child.id category_id , child.name category_name FROM categories child INNER JOIN categories parent ON child.parent_category_id = parent.id WHERE child.parent_category_id IS NOT NULL ORDER BY child.name ) ) parents_with_children ORDER BY parent_category_name, category_name ) ordered_parents_with_children ORDER BY ROW_NUMBER ) category_positions_sorted_alphabetically ) subquery WHERE id = subquery.category_id")
2 « J'aime »

I’ve not tested this recently but here’s at least a hint for how to alpha-sort categories at the rails console:

# alpha sort all categories matching search and their sub-categories

  def sort_matching_categories_and_subcategories(search)
    categories = Category.where("name like ?", search)
    position = 100
    categories.order(:name).each do |cat|
      position += 5
      cat.position = position
      cat.save!()
      c_position = 0
      children = Category.where(:parent_category_id=>cat.id)
      children.order(:name).each do |c|
        c_position += 5
        c.position = c_position
        c.save!()
      end
    end
  end


 # alpha sort subcategories of a single category matching search
def sort_matching_subcategories(search)
  categories = Category.where("name like ?", search)
  if categories.count > 1
    puts "Found more than one category"
  end
  categories.order(:name).each do |cat|
    c_position = 5
    children = Category.where(:parent_category_id=>cat.id)
    children.order(:name).each do |c|
      c_position += 5
      c.position = c_position
      c.save!()
    end
  end
end
1 « J'aime »

Thanks @pfaffman

Based on your ruby code I came up with

def sort_categories_by_name(skip=0)
  
  parents = Category.where("parent_category_id is null")
  position = 0
  parents.order(:name).each do |parent|
    parent.position = position
    parent.save!()
    position += (1+skip)
    children = Category.where(:parent_category_id=>parent.id)
    children.order(:name).each do |child|
      child.position = position
      child.save!()
      position += (1+skip)  
    end
  end
  
  position += -(1+skip)  
  return position
  
end

sort_categories_by_name
1 « J'aime »

Bonjour. Première visite ici.
Ce post précise-t-il que les catégories ne peuvent pas être triées par ordre alphabétique via une option d’interface graphique ?

Merci

En quelque sorte. Il existe des paramètres pour les placer dans un ordre fixe. Je pense que vous devez d’abord configurer un paramètre système (cherchez « fixe », peut-être), puis vous pouvez le faire dans l’interface utilisateur.

Si vous en avez une douzaine, ce n’est pas trop pénible de le faire via l’interface utilisateur (cette interface a posé des problèmes et je ne sais pas comment elle fonctionne aujourd’hui, donc certaines de ces informations pourraient être incorrectes). Si vous en avez des centaines et qu’ils ne changent pas, j’ai autrefois écrit un script à exécuter dans la console pour les trier. Si vous en avez beaucoup, que vous les modifiez constamment et que vous souhaitez les garder triés, vous aurez besoin d’un plugin.

Merci. Je suis simplement un utilisateur du forum Freephone et j’ai demandé aux modérateurs s’ils pouvaient modifier l’ordre de la liste, mais la réponse initiale a été de consulter ce forum pour savoir comment faire, donc ce n’est clairement pas une option facilement accessible, je suppose.

Merci encore

À moins qu’il y ait des dizaines de catégories, ce n’est vraiment pas grave. Et s’ils vous ont envoyé ici plutôt que de consulter les paramètres eux-mêmes ou de poser la question ici, c’est simplement qu’ils ne veulent pas s’en charger.

Merci encore.

Je pense que les modérateurs n’ont pas accès au backend, ce qui semble essentiel.

Je vais donc en télécharger et en héberger un, puis je devrais pouvoir comprendre comment faire ce que je souhaite et partager les informations :slight_smile: Il doit y avoir un administrateur capable de résoudre le problème.

1 « J'aime »

Il semble qu’un des modérateurs sache comment faire, je vous tiendrai au courant. On dit que cela peut se faire via le menu hamburger ??