Kategorien mit SQL sortieren

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 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

Hallo. Ich bin zum ersten Mal hier.
Klärt dieser Beitrag, dass Kategorien nicht über eine GUI-Option alphabetisch sortiert werden können?

Vielen Dank

Ja, so in etwa. Es gibt Einstellungen, um sie in einer festen Reihenfolge anzuzeigen. Ich glaube, man stellt zunächst eine Systemeinstellung ein (suche vielleicht nach ‘fixed’), und danach kann man es in der Benutzeroberfläche erledigen.

Wenn du ein Dutzend hast, ist es nicht allzu schlimm, das in der Benutzeroberfläche zu machen (diese Schnittstelle war schon immer problematisch, und ich weiß nicht mehr genau, wie sie heutzutage funktioniert, daher könnte einiges davon falsch sein). Wenn du aber Hunderte hast und sie nicht häufig änderst, habe ich einmal etwas geschrieben, das über die Konsole läuft, um sie zu sortieren. Wenn du viele hast, sie ständig änderst und sortiert halten möchtest, bräuchtest du ein Plugin.

Danke. Ich bin nur ein Benutzer des ‘Discourse’-Freephone-Forums und habe die Moderatoren gefragt, ob sie die angezeigte Reihenfolge ändern könnten. Die erste Antwort war jedoch, dieses Forum zu konsultieren, um herauszufinden, wie das geht. Das ist also offensichtlich keine einfach verfügbare Option, wie ich vermute.

Nochmals vielen Dank

Wenn es nicht Dutzende von Kategorien gibt, ist das einfach kein großes Problem. Und wenn sie dich hierher geschickt haben, statt selbst in den Einstellungen nachzuschauen oder hier selbst zu fragen, dann wollen sie es einfach nicht machen.

Nochmals vielen Dank.

Ich glaube, die Moderatoren haben keinen Zugriff auf das Backend, was doch eigentlich wichtig ist.

Ich werde es mir also herunterladen und selbst hosten, dann sollte ich herausfinden können, wie man das macht, was ich will, und die Informationen weitergeben können :slight_smile: Es muss doch einen Administrator geben, der das Problem lösen kann.

1 „Gefällt mir“

Sieht so aus, als wüsste einer der Moderatoren, wie es geht. Ich gebe dir Bescheid. Es heißt, man kann es über das Hamburger-Menü machen??